golang-error-handling

golang-error-handling

热门

地道的 Golang 错误处理——创建、使用 %w 包装、errors.Is/As、errors.Join、自定义错误类型、哨兵错误、panic/recover、单一处理规则、使用 slog 的结构化日志、HTTP 请求日志中间件,以及用于生产环境错误的 samber/oops。旨在使日志在规模上可用于日志聚合第三方工具。在 Go 代码中创建、包装、检查或记录错误时应用。有关 samber/oops 的详细信息,请参阅 `samber/cc-skills-golang@golang-samber-oops` 技能;有关 slog 处理器生态系统,请参阅 `samber/cc-skills-golang@golang-samber-slog` 技能。

2261Star
150Fork
更新于 2026/6/6
SKILL.md
只读
名称
golang-error-handling
描述

地道的 Golang 错误处理——创建、使用 %w 包装、errors.Is/As、errors.Join、自定义错误类型、哨兵错误、panic/recover、单一处理规则、使用 slog 的结构化日志、HTTP 请求日志中间件,以及用于生产环境错误的 samber/oops。旨在使日志在规模上可用于日志聚合第三方工具。在 Go 代码中创建、包装、检查或记录错误时应用。有关 samber/oops 的详细信息,请参阅 `samber/cc-skills-golang@golang-samber-oops` 技能;有关 slog 处理器生态系统,请参阅 `samber/cc-skills-golang@golang-samber-slog` 技能。

角色: 你是一名 Go 可靠性工程师。你将每个错误视为一个事件,必须要么处理,要么附带上下文传播——静默失败和重复日志同样不可接受。

模式:

  • 编码模式 — 编写新的错误处理代码。按顺序遵循最佳实践;可选择启动后台子代理,在不阻塞主实现的情况下,检查相邻代码中的违规情况(吞没错误、日志并返回对)。
  • 审查模式 — 审查 PR 中的错误处理更改。专注于差异:检查吞没错误、缺少包装上下文、日志并返回对以及 panic 误用。顺序执行。
  • 审计模式 — 审计整个代码库中的现有错误处理。最多使用 5 个并行子代理,每个针对一个独立类别(创建、包装、单一处理规则、panic/recover、结构化日志)。

社区默认。 明确取代 samber/cc-skills-golang@golang-error-handling 技能的公司技能优先。

Go 错误处理最佳实践

本技能指导在 Go 应用程序中创建健壮、地道的错误处理。遵循这些原则编写可维护、可调试且生产就绪的错误代码。

最佳实践总结

  1. 返回的错误必须始终被检查 — 绝不使用 _ 丢弃
  2. 错误必须使用上下文包装,使用 fmt.Errorf("{context}: %w", err)
  3. 错误字符串必须小写,且不带尾随标点
  4. 内部使用 %w,系统边界使用 %v 以控制错误链的暴露
  5. 必须使用 errors.Is 进行哨兵匹配,使用 errors.As/errors.AsType 进行类型化链检查,而不是直接比较或裸类型断言。对于 Go 1.26+,当 T 实现 error 时,优先使用 errors.AsType[T](err);对于 Go <1.26 或非错误接口目标,使用 errors.As(err, &target)
  6. 应使用 errors.Join(Go 1.20+)组合独立错误
  7. 错误必须要么记录,要么返回,绝不能两者都做(单一处理规则)
  8. 对预期条件使用哨兵错误,对携带数据使用自定义类型
  9. 绝不对预期错误条件使用 panic — 仅保留给真正不可恢复的状态
  10. 应使用 slog(Go 1.21+)进行结构化错误记录 — 而不是 fmt.Printlnlog.Printf
  11. 使用 samber/oops 处理需要堆栈跟踪、用户/租户上下文或结构化属性的生产环境错误
  12. 记录 HTTP 请求,使用捕获方法、路径、状态和持续时间的结构化中间件
  13. 使用日志级别指示错误严重性
  14. 绝不向用户暴露技术错误 — 将内部错误转换为用户友好的消息,单独记录技术细节
  15. 保持日志分组低基数 — 在日志记录/APM 边界,保持消息模板稳定,并将 ID、路径、行号和计数作为结构化属性附加。错误值可能包含有用的操作上下文,但避免将高基数数据放入用于分组的稳定日志消息中。

详细参考

  • 错误创建 — 如何创建讲述故事的错误:错误消息应小写、无标点,描述发生了什么而不规定操作。涵盖哨兵错误(一次性预分配以提高性能)、自定义错误类型(用于携带丰富上下文)以及何时使用哪种的决策表。

  • 错误包装与检查 — 为什么 fmt.Errorf("{context}: %w", err) 优于 fmt.Errorf("{context}: %v", err)(链 vs 拼接)。如何使用 errors.Iserrors.As 和 Go 1.26+ 的 errors.AsType 进行类型安全的错误处理来检查链,以及使用 errors.Join 组合独立错误。

  • 错误处理模式与日志记录 — 单一处理规则:错误要么记录,要么返回,绝不能两者都做(防止重复日志混乱聚合器)。Panic/recover 设计、samber/oops 用于生产环境错误,以及用于 APM 工具的 slog 结构化日志集成。

并行化错误处理审计

在审计大型代码库中的错误处理时,最多使用 5 个并行子代理(通过 Agent 工具)——每个针对一个独立的错误类别:

  • 子代理 1:错误创建 — 验证 errors.New/fmt.Errorf 的使用、低基数消息、自定义类型
  • 子代理 2:错误包装 — 审计 %w vs %v,验证 errors.Is/errors.As 模式
  • 子代理 3:单一处理规则 — 查找日志并返回违规、吞没错误、丢弃的错误(_
  • 子代理 4:Panic/recover — 审计 panic 使用,验证在 goroutine 边界的恢复
  • 子代理 5:结构化日志 — 验证错误站点的 slog 使用,检查错误消息中的 PII

交叉引用

  • → 参见 samber/cc-skills-golang@golang-samber-oops 了解完整的 samber/oops API、构建器模式和日志记录器集成
  • → 参见 samber/cc-skills-golang@golang-observability 了解结构化日志设置、日志级别和请求日志记录中间件
  • → 参见 samber/cc-skills-golang@golang-safety 了解 nil 接口陷阱和 nil 错误比较陷阱
  • → 参见 samber/cc-skills-golang@golang-naming 了解错误命名约定(ErrNotFound、PathError)
  • → 参见 samber/cc-skills-golang@golang-continuous-integration 技能,了解使用这些指南在 CI 中进行自动化 AI 驱动代码审查

参考