golang 打印error的堆栈信息操作
- 作者: -苏丶冷
- 来源: 51数据库
- 2021-06-30
众所周知,目前的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.
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。
推荐阅读
