在Golang中有多种声明错误的方式:
errors.New对于简单的静态字符串的错误fmt.Errorf用于格式化的错误字符串- 实现
Error()方法的自定义错误类型 - 用
"pkg/errors".Wrap的 包装错误
当返回错误时,请考虑以下内容以确定最佳选择:
- 如果是一个简单的错误并且不需要额外的信息,那么
errors.New就可以满足。 - 如果客户端需要检测并且处理错误,那么你需要自定义一个错误类型,并且实现Error()方法。
- 如果你需要传播下游函数返回的错误,那么你需要对此类错误进行相应的包装。
- 其他情况,
fmt.Errorf即可满足需求
如果客户端需要检测错误,并且您已经使用errors.New创建了一个简单的错误,请使用var定义有一个错误变量。
Bad
// package foo
//直接返回一个error
func Open() error {
return errors.New("could not open")
}
// package bar
func use() {
//直接返回一个错误
if err := foo.Open(); err != nil {
//通过的错误的描述信息进行判断
if err.Error() == "could not open" {
// handle
} else {
panic("unknown error")
}
}
}
Good
// package foo
//在foo包中,定义一个ErrCouldNotOpen 变量,并且此变量是可以导出的(首字母大写)
var ErrCouldNotOpen = errors.New("could not open")
func Open() error {
//直接返回错误变量
return ErrCouldNotOpen
}
// package bar
//在bar包中,
if err := foo.Open(); err != nil {
//根据变量类型进行判断
if err == foo.ErrCouldNotOpen {
// handle
} else {
panic("unknown error")
}
}
如果你有一个错误,客户端可能需要进行检测判断,而且你期望还要添加更多的信息(例如,它不是一个静态的字符串),此种情况,你需要一个自定义的错误类型。
Bad
func open(file string) error {
//直接返回错误
return fmt.Errorf("file %q not found", file)
}
func use() {
if err := open("testfile.txt"); err != nil {
//根据错误内容进行判断
if strings.Contains(err.Error(), "not found") {
// handle
} else {
panic("unknown error")
}
}
}
Good
//自定义一个错误类型
type errNotFound struct {
file string
}
//实现Error()方法
func (e errNotFound) Error() string {
return fmt.Sprintf("file %q not found", e.file)
}
//直接返回自定义的错误类型,并且实时修改错误内容
func open(file string) error {
return errNotFound{file: file}
}
func use() {
if err := open("testfile.txt"); err != nil {
//通过类型断言
if _, ok := err.(errNotFound); ok {
// handle
} else {
panic("unknown error")
}
}
}
在直接导出自定义错误类型时要小心,因为它们已成为包的公共API的一部分。稳妥的办法是是公开匹配器函数,来鉴别错误类型。
// package foo
//在 foo 包中,自定义错误类型
type errNotFound struct {
file string
}
//实现Error()方法
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
// 在 bar 包中,调用foo包中导出的方法
if err := foo.Open("foo"); err != nil {
if foo.IsNotFoundError(err) {
// handle
} else {
panic("unknown error")
}
}
本文介绍了在Golang中处理错误的不同方式,包括errors.New、fmt.Errorf、自定义错误类型和错误包装。强调了根据错误处理需求选择适当方法的重要性,如使用预定义错误变量便于类型判断,自定义错误类型以提供更多信息,以及通过包装错误来传播下游错误。建议在公开错误类型时提供匹配器函数以避免暴露过多API细节。
1720

被折叠的 条评论
为什么被折叠?



