★ gerror/gcode 错误体系:New/Wrap/Is/Equal/错误码
结论:gerror 提供“带堆栈、可包装、可成链”的错误对象(New/Wrap 构造、Cause 找根因、Stack 打堆栈),gcode 负责把错误分类为可对外的错误码;controller 层只需 return err,框架按 code/message 统一回给前端。
一、核心 API
| 用途 | API | 说明 |
|---|
| 构造 | gerror.New/Newf、NewCode/NewCodef | 新错误,可携带错误码 |
| 包装 | gerror.Wrap/Wrapf、WrapCode | 保留根因与堆栈并追加上下文 |
| 提取 | gerror.Cause(err) | 取错误链根因 |
| 堆栈 | gerror.Stack(err) | 打印完整堆栈 |
| 判断 | gerror.Is/Equal、标准库 errors.Is/As | 错误链包含/相等判断(细节以官方文档为准) |
| 错误码 | gerror.Code(err)、gcode.New | 提取/构造错误码 |
二、常用内建错误码(编号以官方 gcode 定义为准)
| 错误码 | 含义 |
|---|
| CodeNil (0) | 成功/无错误 |
| CodeInternalError (50) | 内部错误 |
| CodeValidationFailed (51) | 参数校验失败 |
| CodeDbOperationError (52) | 数据库操作错误 |
| CodeInvalidParameter (53) | 非法参数 |
| CodeUnauthorized (61) | 未认证/未授权 |
| CodeNotFound (65) | 资源不存在 |
代码示例
// 业务错误码(建议集中定义并登记在错误码表)
var CodeBalanceNotEnough = gcode.New(10001, "余额不足", nil)
// 业务层:包装后上抛,保留现场
func (l *userLogic) Transfer(ctx context.Context, ...) error {
if balance < amount {
return gerror.NewCode(CodeBalanceNotEnough, "转账失败")
}
return gerror.Wrap(err, "扣款失败")
}
// 上层判断
code := gerror.Code(err) // 提取错误码(gcode.Code)
g.Log().Error(ctx, code.Code(), code.Message())
常见追问 / 记忆点
- 追问:为什么不直接 fmt.Errorf?→ 可以,但 gerror 会保留更完整堆栈并携带错误码,与统一返回/日志排障配合更好。
- 追问:Wrap 与 New 的区别?→ Wrap 基于已有 error 追加信息并保留根因链,New 创建全新错误。
- 记忆点:New 建错、Wrap 追因、Cause 挖根、Code 分类——“业务错误必须带码,吞错必须 Wrap”。