Go 结构化错误处理库,在标准 error 基础上提供错误码、HTTP 状态码、调用栈追踪、上下文字段和客户端消息本地化能力。
- 双消息体系:
Message() 面向用户/API,Error() 面向日志/调试
- 结构化错误码:通过
XCode 统一管理错误码、HTTP 状态码和消息
- 不可变错误:
WithFields() 返回新实例,并发安全
- 客户端本地化:同一错误码根据不同客户端返回不同消息
- 错误码注册表:支持运行时
Override 和 Reset
- 调用栈追踪:
%+v 输出完整调用栈
- 兼容层:提供
pkg/errors 兼容函数签名
go get github.com/gomooth/xerror
package main
import (
"fmt"
"github.com/gomooth/xerror"
"github.com/gomooth/xerror/xcode"
)
func main() {
// 基本创建
err := xerror.New("简单错误")
fmt.Println(err.Message()) // "简单错误"
fmt.Println(err.ErrorCode()) // -1 (CodeNone)
// 带错误码
err = xerror.NewCode(100001, "未登录")
fmt.Println(err.Message()) // "未登录"
fmt.Println(err.ErrorCode()) // 100001
fmt.Println(err.Error()) // "[100001] 未登录"
// 使用预定义 XCode
err = xerror.NewXCode(xcode.Forbidden)
fmt.Println(err.HttpStatus()) // 403
// 包装错误
err = xerror.Wrap(err, "无权访问该资源")
fmt.Println(err.Message()) // "无权访问该资源"
fmt.Println(err.Error()) // "[403] 无权访问该资源: 无权访问"
// 附加上下文字段
err = xerror.NewCode(100001, "未登录").
WithFields(xerror.F("userId", 12345))
fmt.Println(xerror.ParsePayload(err)) // {"userId":12345}
// 错误比较
if xerror.IsXCode(err, xcode.Forbidden) {
fmt.Println("是无权访问错误")
}
if xerror.IsErrorCode(err, 100001) {
fmt.Println("是未登录错误")
}
}
XError 组合了 CodeCarrier、FieldCarrier、Messenger 三个子接口,并扩展了包装与本地化能力。
| 方法 |
说明 |
Message() |
面向用户/API 的消息(无码前缀) |
ChainMessage() |
从当前层向下拼接的完整消息链(无码前缀) |
Error() |
面向日志的消息,格式 [code] chain_message |
ErrorCode() |
错误码 |
HttpStatus() |
HTTP 状态码 |
XCode() |
底层 XCode |
WithFields(...Field) |
附加字段(返回新实例,不可变) |
GetFields() |
返回字段切片的安全副本 |
WithHttpStatus(int) |
修改 HTTP 状态码(返回新实例) |
ToMessage(*ecode.Config) |
客户端本地化消息 |
Is(error) |
判断是否与目标错误相等 |
Unwrap() |
解包获得内层 error |
| 函数 |
说明 |
New(message) |
创建纯消息错误,错误码为 CodeNone(-1) |
NewCode(code, message) |
使用错误码创建,从注册表继承 httpStatus |
NewCodef(code, format, args...) |
使用错误码创建格式化错误 |
NewXCode(code, message...) |
使用 XCode 创建,可选 message 覆盖 XCode 消息 |
NewXCodef(code, format, args...) |
使用 XCode 创建格式化错误 |
| 函数 |
httpStatus 来源 |
消息来源 |
fields |
场景 |
Wrap |
原错误码 |
传入 message |
继承 |
添加上下文 |
WrapWithCode |
注册表 |
原错误消息 |
继承 |
指定错误码包装 |
WrapWithXCode |
XCode |
XCode |
继承 |
屏蔽细节,统一对外 |
WrapStatus |
XCode |
原错误 |
继承 |
修正 HTTP 状态码 |
WrapSanitize |
原错误码 |
传入 message |
不继承 |
清洗字段,防泄露 |
| 函数 |
说明 |
Cause(err) |
返回下一个业务层错误 |
RootCause(err) |
返回错误链最深层错误 |
AsXError(err) |
从错误链提取 XError |
IsXCode(err, code) |
判断错误是否匹配指定 XCode |
IsErrorCode(err, code) |
判断错误是否匹配指定错误码 |
CollectCodes(err) |
递归收集错误链中所有错误码 |
| 函数 |
说明 |
ParsePayload(err) |
提取错误的结构化字段为 map |
CollectFields(err) |
递归收集错误链中所有字段 |
StackTrace(err) |
返回调用栈文本 |
FormatMsg(err) |
格式化错误消息(含码和字段) |
FormatPayloadFields(fields) |
格式化字段为可读字符串 |
ToClientMessage(err, client, repo) |
转换为客户端特定消息 |
| 函数 |
说明 |
Errorf(format, args...) |
格式化创建错误,支持 %w |
Wrapf(err, format, args...) |
格式化包装错误 |
WithMessage(err, message) |
附加消息 |
WithMessagef(err, format, args...) |
附加格式化消息 |
| 函数 |
说明 |
JoinXErrors(errs...) |
合并多个 XError |
JoinErrors(errs...) |
合并多个 error(支持混合类型) |
| 范围 |
用途 |
管理方式 |
| -1000 ~ 9999 |
系统保留码 |
内部预定义 |
| >= 10000 |
业务码 |
Register() 外部注册 |
MIT License