错误类型
有很多种方法来声明 errors:
errors.New
声明简单的静态字符串错误信息fmt.Errorf
声明格式化的字符串错误信息- 为自定义类型实现
Error()
方法 - 通过
"pkg/errors".Wrap
包装错误类型
返回错误时,请考虑以下因素来作出最佳选择:
- 这是一个不需要其他额外信息的简单错误吗?如果是,使用
error.New
。 - 客户需要检测并处理此错误吗?如果是,那应该自定义类型,并实现
Error()
方法。 - 是否是在传递一个下游函数返回的错误?如果是,请查看error 封装部分。
- 其他,使用
fmt.Errorf
。
如果客户需要检测错误,并且是通过 errors.New
创建的一个简单的错误,请使用var 声明这个错误类型。
Bad | Good |
---|---|
|
|
如果你有一个错误需要客户端来检测,并且你想向其添加更多信息(例如,它不是一个简单的静态字符串),那么应该声明一个自定义类型。
Bad | Good |
---|---|
|
|
直接将自定义的错误类型设为导出需要特别小心,因为这意味着他们已经成为包的公开 API 的一部分了。更好的方式是暴露一个匹配函数来检测错误。
// package foo
type errNotFound struct {
file string
}
func (e errNotFound) Error() string {
return fmt.Sprintf("file %q not found", e.file)
}
func IsNotFoundError(err error) bool {
_, ok := err.(errNotFound)
return ok
}
func Open(file string) error {
return errNotFound{file: file}
}
// package bar
if err := foo.Open("foo"); err != nil {
if foo.IsNotFoundError(err) {
// handle
} else {
panic("unknown error")
}
}