error的底层
error就是一个接口
type error interface{
Error()string
}
errors包常用的New理如下
func New(s string){
return &errorString{s}
}
type errorString struct{
s string
}
func (e *errorString)Error(){
return e.s
}
一般New中的参数首字母小写结尾不加标点
error的使用原则
视之为值
将实现Error的都看做error处理的方式有下面三种
- 哨兵
出现错误,就及时发现,不在继续进行
- 错误类型
在实现Error的结构体中,添加一些字段,存储上下文信息,表示错误的类型
//PathError不是error类型,没有实现Error,虽然内部含有error
type PathError struct {
Op string
Path string
Err error
}
外层需要断言
switch v:=v(type){
case *PathError:
//.....
}
- 黑盒
不知道返回错误的类型,遇到这种情况,直接返回错误
有时候直接返回错误还不够,虽然不知道具体类型,但可以判断错误是否实现了某接口,这样可以继续进行操作
type temp interface{
Temp() bool
}
func isTemp(err error) bool{
e,ok:=err.(temp) //断言会进行类型转化
return ok&&e.temp()
}
优雅处理
用Wrap封装error,错误处理尽量简洁
一次处理
下面是两次处理
if err!=nil{
log.Println("oops")
return err
}
这里写入了日志一次,然后返回err,加入上一层也做同样的处理,日志中会有大量重复的信息