项目中错误处理
目录
项目中底层函数错误上报不能带上文件名和行号,后面查找很难,有些函数甚至同样的错误信息,比如
func AAA() error {
if ...{
return errors.New("file write err")
}
...
if ...{
return errors.New("file write err")
}
}
pkg/errors
使用实例:
import (
"errors"
"fmt"
pkgError "github.com/pkg/errors"
)
func main() {
err := test3()
fmt.Printf("%+v\n",err) // 打印原始err及调用栈信息
fmt.Println(pkgError.Cause(err)) // 获取原始err
fmt.Println(pkgError.Is(err,TestErr)) // 对比原始err
}
func test3() error {
return pkgError.WithMessage(test2(),"this is test3")
}
func test2() error {
return pkgError.WithMessage(test1(),"this is test2")
}
var TestErr =errors.New("test err")
func test1() error {
return pkgError.Wrap(TestErr,"this is test1")
}
我们只需要在第一次出现err的地方wrap即可,不然会打印重复的调用栈信息,没有啥用。
go1.3error
1.3对参考pkg/errors引入As,Is,Wrap,Unwrap
func main() {
err := test3()
fmt.Printf("%+v\n",err) // 打印原始err及调用栈信息
fmt.Println(errors.Unwrap(err)) // 和%w是反向操作,一次只能剥一层
fmt.Println(errors.Is(err,TestErr)) // 对比原始err
}
func test3() error {
return fmt.Errorf("%w,this is test3",test2())
}
func test2() error {
return fmt.Errorf("%w,this is test2",test1())
}
var TestErr =errors.New("test err")
func test1() error {
return fmt.Errorf("%w,this is test1",TestErr) // 通过%w来wrap error
}
打印:
test err,this is test1,this is test2,this is test3
test err,this is test1,this is test2
true
其实还是没有打印调用栈,并不能快速定位到文件和行
引发的打印思考
pkg/errors,要想打印出调用栈必须使用%+v,%v和%#v都不行,而且他这打印出非常规格式的属于定制,是怎么做到的? 看了代码发现他有函数:
func (f *fundamental) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
io.WriteString(s, f.msg)
f.stack.Format(s, verb)
return
}
fallthrough
case 's':
io.WriteString(s, f.msg)
case 'q':
fmt.Fprintf(s, "%q", f.msg)
}
}
在这里判断了+v符号,所以只有这种情形才能打印,如果定义了一个结构体,想自定义打印样式,可以实现这个方法。