
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` 技能。
地道的 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 应用程序中创建健壮、地道的错误处理。遵循这些原则编写可维护、可调试且生产就绪的错误代码。
最佳实践总结
- 返回的错误必须始终被检查 — 绝不使用
_丢弃 - 错误必须使用上下文包装,使用
fmt.Errorf("{context}: %w", err) - 错误字符串必须小写,且不带尾随标点
- 内部使用
%w,系统边界使用%v以控制错误链的暴露 - 必须使用
errors.Is进行哨兵匹配,使用errors.As/errors.AsType进行类型化链检查,而不是直接比较或裸类型断言。对于 Go 1.26+,当T实现error时,优先使用errors.AsType[T](err);对于 Go <1.26 或非错误接口目标,使用errors.As(err, &target)。 - 应使用
errors.Join(Go 1.20+)组合独立错误 - 错误必须要么记录,要么返回,绝不能两者都做(单一处理规则)
- 对预期条件使用哨兵错误,对携带数据使用自定义类型
- 绝不对预期错误条件使用
panic— 仅保留给真正不可恢复的状态 - 应使用
slog(Go 1.21+)进行结构化错误记录 — 而不是fmt.Println或log.Printf - 使用
samber/oops处理需要堆栈跟踪、用户/租户上下文或结构化属性的生产环境错误 - 记录 HTTP 请求,使用捕获方法、路径、状态和持续时间的结构化中间件
- 使用日志级别指示错误严重性
- 绝不向用户暴露技术错误 — 将内部错误转换为用户友好的消息,单独记录技术细节
- 保持日志分组低基数 — 在日志记录/APM 边界,保持消息模板稳定,并将 ID、路径、行号和计数作为结构化属性附加。错误值可能包含有用的操作上下文,但避免将高基数数据放入用于分组的稳定日志消息中。
详细参考
-
错误创建 — 如何创建讲述故事的错误:错误消息应小写、无标点,描述发生了什么而不规定操作。涵盖哨兵错误(一次性预分配以提高性能)、自定义错误类型(用于携带丰富上下文)以及何时使用哪种的决策表。
-
错误包装与检查 — 为什么
fmt.Errorf("{context}: %w", err)优于fmt.Errorf("{context}: %v", err)(链 vs 拼接)。如何使用errors.Is、errors.As和 Go 1.26+ 的errors.AsType进行类型安全的错误处理来检查链,以及使用errors.Join组合独立错误。 -
错误处理模式与日志记录 — 单一处理规则:错误要么记录,要么返回,绝不能两者都做(防止重复日志混乱聚合器)。Panic/recover 设计、
samber/oops用于生产环境错误,以及用于 APM 工具的slog结构化日志集成。
并行化错误处理审计
在审计大型代码库中的错误处理时,最多使用 5 个并行子代理(通过 Agent 工具)——每个针对一个独立的错误类别:
- 子代理 1:错误创建 — 验证
errors.New/fmt.Errorf的使用、低基数消息、自定义类型 - 子代理 2:错误包装 — 审计
%wvs%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 驱动代码审查





