golang 打印error的堆栈信息操作
程序员文章站
2022-03-23 14:33:43
众所周知,目前的golang error只关注error()信息,而不关注它的堆栈路径,对错误的定位大多数通过log.setflags(log.llongfile| log.lstdflags)log...
众所周知,目前的golang error只关注error()信息,而不关注它的堆栈路径,对错误的定位大多数通过
log.setflags(log.llongfile| log.lstdflags) log.println(e)
一旦代码分层,为了定位错误,可能出现每一个层次的同一个error,都得log好几次,比如:
func db()error{ return errors.new("time out") } func dao()error{ if er:= db();er!=nil{ log.println(er) return error } return nil } func service()error{ if er:= dao();er!=nil{ log.println(er) return error } return nil } func control()error{ if er:= service();er!=nil{ log.println(er) return error } return nil }
如何一次性抛出错误,把该错误的堆栈全部都拿住呢
以模拟一次请求-分发-服务-数据库操作为例:
package main import ( "errors" "fmt" "github.com/fwhezfwhez/errorx" ) func main() { if e := control(); e != nil { e.(errorx.error).printstacktrace() // log.println(e.(errorx.error).stacktrace()) } else { reply() } } // assume an engine to connect mysql func db() error { return errors.new("connect to mysql time out") } // handle database operation func dao() error { if er := db(); er != nil { return errorx.new(er) } return nil } // handle logic service func service() error { if er := dao(); er != nil { return errorx.wrap(er) } return nil } // handle request distribute from main func control() error { if er := service(); er != nil { return errorx.regen(er, errors.new("inner service error,please call admin for help")) } return nil } // reply a the request func reply(){ fmt.println("handle success") }
执行结果:
stacktrace | causedby
g:/go_workspace/gopath/src/errorx/example/main.go: 26 | connect to mysql time out
g:/go_workspace/gopath/src/errorx/example/main.go: 34 | connect to mysql time out
g:/go_workspace/gopath/src/errorx/example/main.go: 42 | inner service error,please call admin for help
补充:golang 异常退出堆栈捕获
利用golang自带包 runtime/debug 异常时打印
debuginfo.go
package main import ( "fmt" "os" "runtime/debug" "time" ) func trye() { errs := recover() if errs == nil { return } exename := os.args[0] //获取程序名称 now := time.now() //获取当前时间 pid := os.getpid() //获取进程id time_str := now.format("20060102150405") //设定时间格式 fname := fmt.sprintf("%s-%d-%s-dump.log", exename, pid, time_str) //保存错误信息文件名:程序名-进程id-当前时间(年月日时分秒) fmt.println("dump to file ", fname) f, err := os.create(fname) if err != nil { return } defer f.close() f.writestring(fmt.sprintf("%v\r\n", errs)) //输出panic信息 f.writestring("========\r\n") f.writestring(string(debug.stack())) //输出堆栈信息 }
测试异常捕获 main.go
package main import ( "fmt" "time" ) func main() { defer trye() fmt.println(time.now()) panic(-2) fmt.println("panic restore now, continue.") }
查看堆栈可以定位main 里第11行抛出异常-2.
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。