Git URL:
1 git://www.github.com/juju/errors.git
quick start 下面是个简单的例子,假如我们的func每次都去向外抛出异常,对于代码跟踪来说说实话很不方便的,所以依靠这个日志很好的定位问题!
1 2 3 4 5 6 7 8 func main () { err := errors.New("1" ) err1 := errors.Trace(err) err2 := errors.Trace(err1) err3 := errors.Trace(err2) stack := errors.ErrorStack(err3) fmt.Println(stack) }
输出:
1 2 3 4 /Users/dong/go/code/github/errors-pck/errors/main.go:9: 1 /Users/dong/go/code/github/errors-pck/errors/main.go:10: /Users/dong/go/code/github/errors-pck/errors/main.go:11: /Users/dong/go/code/github/errors-pck/errors/main.go:12:
如果在业务中,我们可能靠打印日志的问题,那么就会造成异常日志难以追踪,必须依赖trace_id,还需要依赖上下文传递,所以这里我们假如使用这个error,那么会带来很多方便的功能,就是很好的定位异常。
比如我举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import ( "context" "fmt" "github.com/juju/errors" ) func findUserNameById (ctx context.Context, id uint64 ) (string , error) { if id == 0 { return "" , errors.Errorf("not fond user , user_id=%d" , id) } return "success" , nil } func GetUserInfo (ctx context.Context, id uint64 ) (interface {}, error) { name, err := findUserNameById(ctx, id) if err != nil { return nil , errors.Annotate(err, "GetUserInfo error" ) } return map [string ]interface {}{ "name" : name, }, nil } func main () { info, err := GetUserInfo(context.Background(), 0 ) if err != nil { errs := errors.ErrorStack(err) fmt.Println(errs) return } fmt.Println(info) }
输出
1 2 /Users/dong/go /code/github/errors-pck/errors/main.go :11 : not fond user , user_id=0 /Users/dong/go /code/github/errors-pck/errors/main.go :19 : GetUserInfo error
所以很轻松的携带了信息,同时很好的记录的异常。如果我们业务去记录大量的日志,对于io的影响很大。
其实对于磁盘来说,单次io的消耗>调用Caller
的消耗,同时省去了trace_id 的烦恼!!!!!!
API 介绍 我相信,业务异常中,大部分都是需要打印参数信息的,所以errorf 是很重要的!!
1 2 3 4 5 func Errorf (format string , args ...interface {}) error { err := &Err{message: fmt.Sprintf(format, args...)} err.SetLocation(1 ) return err }
errors.Trace(error)
如果你想函数传递过程中记录你这个error抛出的位置,记得调用trace
方法!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func findUserNameById (ctx context.Context, id uint64 ) (string , error) { if id == 0 { return "" , errors.New("find err" ) } return "success" , nil } func GetUserInfo (ctx context.Context, id uint64 ) (interface {}, error) { name, err := findUserNameById(ctx, id) if err != nil { return nil , err } return map [string ]interface {}{ "name" : name, }, nil }
输出:
1 /Users/dong/go /code/github/errors-pck/errors/main.go :11 : find err
errors.Annotate(error,msg)
如果我们向外抛出的时候,还想记录一些信息,那么很棒,这个方法就是!!! 是不是很nice!
1 2 3 4 5 6 7 8 9 func GetUserInfo (ctx context.Context, id uint64 ) (interface {}, error) { name, err := findUserNameById(ctx, id) if err != nil { return nil , errors.Annotate(err, "我要记录一下" ) } return map [string ]interface {}{ "name" : name, }, nil }
输出:
1 2 3 /Users/dong/go /code/github/errors-pck/errors/main.go :11 : not fond user , user_id=0 /Users/dong/go /code/github/errors-pck/errors/main.go :19 : 我要记录一下
wraper 的方式,我感觉使用场景并不多,所以并没有care到多少!
1 2 3 4 5 6 7 8 9 10 11 12 func GetUserInfo (ctx context.Context, id uint64 ) (interface {}, error) { name, err := findUserNameById(ctx, id) if err != nil { return nil , errors.Wrapf(err, errors.New("GetUserInfo" ), "GetUserInfo" ) } return map [string ]interface {}{ "name" : name, }, nil } /Users/dong/go /code/github/errors-pck/errors/main.go :23 : not fond user , user_id=0 /Users/dong/go /code/github/errors-pck/errors/main.go :31 : GetUserInfo: GetUserInfo
errors.NewBadRequest(err,msg)
和 errors.IsBadRequest(err)
一些类型判断的函数,比如我异常类型又多个,需要判断,所以就需要这个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func main () { request := errors.NewBadRequest(errors.Errorf("err" ), "111" ) fmt.Println(errors.IsBadRequest(request)) } type badRequest struct { Err } func NewBadRequest (err error, msg string ) error { return &badRequest{wrap(err, msg, "" )} } func IsBadRequest (err error) bool { err = Cause(err) _, ok := err.(*badRequest) return ok }
不怕传递空
1 2 3 4 5 6 func main () { request := errors.NewBadRequest(nil , "111" ) fmt.Println(errors.IsBadRequest(request)) }