Error接口

Go语言不支持其他语言使用try/catch方式捕获处理错误,而是将错误作为一种特殊的值来处理。

Go语言使用了一个名为 error 接口来表示错误类型

1
2
3
type error interface {
Error() string
}

当一个函数或方法需要返回错误时,我们通常是把错误作为最后一个返回值。例如下面标准库 os 中打开文件的函数

1
2
3
func Open(name string) (*File, error) {
return OpenFile(name, O_RDONLY, 0)
}

errors.New

创建错误的最简单的方式就用errors.New()函数来创建一个错误

1
2
3
4
5
6
func queryById(id int64) (*Info, error) {
if id <= 0 {
return nil, errors.New("无效的id")
}
//...
}

它接收一个字符串参数返回包含该字符串的错误。

fmt.Errorf

这个相当于是一个格式化版的New函数,可以格式化地创建一个错误。经常的,我们需要在传出的错误中包含一个错误,且将其错误进行二次包装,这时候我们使用fmt.Errorf时搭配使用特殊的格式化动词%w,可以实现基于已有的错误再包装得到一个新的错误。

1
fmt.Errorf("查询数据库失败,err:%w", err)

对于这种二次包装的错误,errors包中提供了以下三个方法。

1
2
3
func Unwrap(err error) error                 // 获得err包含下一层错误
func Is(err, target error) bool // 判断err是否包含target
func As(err error, target interface{}) bool // 判断err是否为target类型

错误结构体类型

我们还可以自己定义结构体类型,来实现``error`接口。

1
2
3
4
5
6
7
8
9
// OpError 自定义结构体类型
type OpError struct {
Op string
}

// Error OpError 类型实现error接口
func (e *OpError) Error() string {
return fmt.Sprintf("无权执行%s操作", e.Op)
}