go使用errors.Wrapf()代替log.Error()方法示例
脚本之家 / 编程助手:解决程序员“几乎”所有问题!
脚本之家官方知识库 → 点击立即使用
引言
介绍不同语言的错误处理机制:
Musings about error handling mechanisms in programming languages
项目中 main调func1,func1调取func2...
这样就会出现很多的 if err != nil { log.Printf()}
, 在Kibana上查看时会搜到多条日志, 需要逐级定位, 确定错误抛出的点
希望只有一条, 能清晰看到整个堆栈调用信息
使用log.xxxx方法
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 37 38 39 40 41 42 43 44 45 46 | package main import ( "fmt" "log" "strconv" "time" ) func init() { log.SetFlags(log.Lshortfile | log.LstdFlags) } func main() { str := "123a" rs, err := func1(str) if err != nil { log.Printf( "err is (%+v)\n" , err) return } fmt. Println ( "最终结果为:" , rs) } func func1(str string ) ( int , error ) { b, err := func2() if err != nil { log.Printf( "There is func11111, func2 err(%+v)\n" , err) } if b == false { strInt, err := strconv.Atoi(str) if err != nil { log.Printf( "There is func11111, err(%+v)\n" , err) } return strInt, err } return 0 , nil } func func2() ( bool , error ) { now := time.Now().Unix() endTimeStr := "2021-08-06 20:00:0000" endtime, err := time.ParseInLocation( "2006-01-02 15:04:05" , endTimeStr, time.Local) if err != nil { log.Printf( "There is func22222, err(%+v)\n" , err) return false , err } if endtime.Unix() > now { return true , nil } return false , nil } |
执行结果:
2021/06/07 21:52:56 vs.go:56: There is func22222, err(parsing time "2021-08-06 20:00:0000": extra text: "00")
2021/06/07 21:52:56 vs.go:33: There is func11111, func2 err(parsing time "2021-08-06 20:00:0000": extra text: "00")
2021/06/07 21:52:56 vs.go:40: There is func11111, err(strconv.Atoi: parsing "123a": invalid syntax)
2021/06/07 21:52:56 vs.go:20: err is (strconv.Atoi: parsing "123a": invalid syntax)
使用errors.Wrapf方法
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 37 38 39 40 41 42 43 44 45 | package main import ( "fmt" "github.com/pkg/errors" "strconv" "time" ) func main() { str := "123a" rs, err := func1(str) if err != nil { fmt.Printf( "err: %+v\n" , err) //fmt.Println("err:", lastErr) //必须%+v才会打印完整堆栈信息,否则只打印错误信息 return } fmt. Println ( "最终结果为:" , rs) } func func1(str string ) ( int , error ) { b, err := func2() if err != nil { err = errors.Wrapf(err, "There is func11111, func2 err, b is(%b) \n" , b) } if b == false { var strInt int strInt, err = strconv.Atoi(str) if err != nil { err = errors.Wrapf(err, "There is func11111,str is(%s)\n" , str) } return strInt, err } return 0 , nil } func func2() ( bool , error ) { now := time.Now().Unix() endTimeStr := "2021-08-06 20:00:0000" endtime, err := time.ParseInLocation( "2006-01-02 15:04:05" , endTimeStr, time.Local) if err != nil { err = errors.Wrapf(err, "There is func22222,endTimeStr is(%s)\n" , endTimeStr) return false , err } if endtime.Unix() > now { return true , nil } return false , nil } |
执行:
err: strconv.Atoi: parsing "123a": invalid syntax
There is func11111,str is(123a)
main.func1
/Users/fliter/go/src/shuang/llog/1.go:39
main.main
/Users/fliter/go/src/shuang/llog/1.go:13
runtime.main
/usr/local/Cellar/go/1.16.3/libexec/src/runtime/proc.go:225
runtime.goexit
/usr/local/Cellar/go/1.16.3/libexec/src/runtime/asm_amd64.s:1371
注意赋值这步, 必不可少!
有一个问题, 即对于f1调f2,f2调f3这种, 如果f3发生error, 可以逐级将error抛出.
但如果一个方法里有两个error, 则第二条会覆盖掉第一条,如上 err = errors.Wrapf(err, "There is func11111, func2 err, b is(%b) \n", b)
这一条就被覆盖了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // Wrapf returns an error annotating err with a stack trace // at the point Wrapf is called, and the format specifier. // If err is nil, Wrapf returns nil. func Wrapf(err error , format string , args ... interface {}) error { if err == nil { return nil } err = &withMessage{ cause: err, msg: fmt.Sprintf(format, args...), } return &withStack{ err, callers(), } } |
1 2 3 4 5 6 7 | func callers() *stack { const depth = 32 var pcs [depth] uintptr n := runtime.Callers( 3 , pcs[:]) var st stack = pcs[ 0 :n] return &st } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // Callers fills the slice pc with the return program counters of function invocations // on the calling goroutine's stack. The argument skip is the number of stack frames // to skip before recording in pc, with 0 identifying the frame for Callers itself and // 1 identifying the caller of Callers. // It returns the number of entries written to pc. // // To translate these PCs into symbolic information such as function // names and line numbers, use CallersFrames. CallersFrames accounts // for inlined functions and adjusts the return program counters into // call program counters. Iterating over the returned slice of PCs // directly is discouraged, as is using FuncForPC on any of the // returned PCs, since these cannot account for inlining or return // program counter adjustment. func Callers(skip int , pc [] uintptr ) int { // runtime.callers uses pc.array==nil as a signal // to print a stack trace. Pick off 0-length pc here // so that we don't let a nil pc slice get to it. if len (pc) == 0 { return 0 } return callers(skip, pc) } |
1 2 3 4 5 6 7 8 9 10 | func callers(skip int , pcbuf [] uintptr ) int { sp := getcallersp() pc := getcallerpc() gp := getg() var n int systemstack( func () { n = gentraceback(pc, sp, 0 , gp, skip, &pcbuf[ 0 ], len (pcbuf), nil , nil , 0 ) }) return n } |
参考:
以上就是go使用errors.Wrapf()代替log.Error()方法示例的详细内容,更多关于go errors.Wrapf log.Error的资料请关注脚本之家其它相关文章!
微信公众号搜索 “ 脚本之家 ” ,选择关注
程序猿的那些事、送书等活动等着你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!
相关文章
VSCode1.4 搭建Golang的开发调试环境(遇到很多问题)
这篇文章主要介绍了VSCode1.4 搭建Golang的开发调试环境(遇到很多问题),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-04-04Golang 中的 unsafe.Pointer 和 uintptr详解
这篇文章主要介绍了Golang中的unsafe.Pointer和uintptr详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下2022-08-08基于go interface{}==nil 的几种坑及原理分析
这篇文章主要介绍了基于go interface{}==nil 的几种坑及原理分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2021-04-04
最新评论