Go Engineering - Foundation - Error - Package
功能需求
- 支持错误堆栈
- 支持不同的打印格式,例如
%+v
、%v
、%s
等 - 支持 Wrap/Unwrap 功能:在已有 error 的基础上,追加一些新的信息
errors.Wrap(err, "open file failed")
- 调用 Wrap 时,会生成一个错误堆栈节点
- 支持 Is 方法:判断某个 error 是否为指定的 error
- Go 1.13 之前,并没有 wrapping error
if err == os.ErrNotExist {}
- 有 wrapping error 后,直接用
==
判断会有问题,因为可能是 wrapping errorfunc Is(err, target error) bool
- err 和 target 是同一个
- 当 err 是 wrapping error 时,target 包含在这个嵌套 error 链中
- Go 1.13 之前,并没有 wrapping error
- 支持 As 函数
- Go 1.13 之前,并没有 wrapping error,可以使用 type assertion 或者 type switch
if perr, ok := err.(*os.PathError); ok {}
- 有 wrapping error 时
var perr *os.PathError
if errors.As(err, &perr) {}
- Go 1.13 之前,并没有 wrapping error,可以使用 type assertion 或者 type switch
- 支持两种错误创建方式
errors.New("file not found")
errors.Errorf("file %s not found", "iam-apiserver")
使用样例
生产环境使用 JSON 格式打印日志,便于后续日志系统的解析,即
%#-v
或%#+v
1 | package main |
1 | [ |
代码实现
withCode
1 | type withCode struct { |
WrapC
1 | func WrapC(err error, code int, format string, args ...interface{}) error { |
init
Must 是一种 Go 代码设计技巧,在不满足某种情况时会 panic,建议使用
1 | // codes contains a map of error codes to metadata. |
1 | // Coder defines an interface for an error code detail information. |
1 | // ErrCode implements `github.com/marmotedu/errors`.Coder interface. |
Is + As + Unwrap
1 | // +build go1.13 |
IsCode
1 | // IsCode reports whether any error in err's chain contains the given error code. |
ParseCoder
1 | // ParseCoder parse any error into *withCode. |
记录错误
利用堆栈
使用样例如上
原始位置
仅在错误产生的最原始位置调用日志包记录函数,打印错误信息,其他位置直接返回
1 | package main |
1 | $ go run errortrack_log.go |
这种情况,一般不需要再对错误进行封装
错误码
通用错误码
1 | package code |
codegen 可以生成 sample_code_generated.go 和 error_code_generated.md
1 | $ make tools.install.codegen |
实际开发过程中,将错误码包独立成一个包,放在
internal/pkg/code/
目录下,方便整个应用调用
业务错误码
1 | $ ls internal/pkg/code |
同一服务不同模块的错误码,使用不同的 const 代码块区分
1 | // iam-apiserver: user errors. |
集成使用
1 | // Response defines project response format which in marmotedu organization. |