golang 打印error的堆棧信息操作
眾所周知,目前的golang error只關(guān)注Error()信息,而不關(guān)注它的堆棧路徑,對(duì)錯(cuò)誤的定位大多數(shù)通過
log.SetFlags(log.Llongfile| log.LstdFlags) log.Println(e)
一旦代碼分層,為了定位錯(cuò)誤,可能出現(xiàn)每一個(gè)層次的同一個(gè)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 }
如何一次性拋出錯(cuò)誤,把該錯(cuò)誤的堆棧全部都拿住呢
以模擬一次請(qǐng)求-分發(fā)-服務(wù)-數(shù)據(jù)庫操作為例:
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") }
執(zhí)行結(jié)果:
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
補(bǔ)充:golang 異常退出堆棧捕獲
利用golang自帶包 runtime/debug 異常時(shí)打印
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() //獲取當(dāng)前時(shí)間 pid := os.Getpid() //獲取進(jìn)程ID time_str := now.Format("20060102150405") //設(shè)定時(shí)間格式 fname := fmt.Sprintf("%s-%d-%s-dump.log", exeName, pid, time_str) //保存錯(cuò)誤信息文件名:程序名-進(jìn)程ID-當(dāng)前時(shí)間(年月日時(shí)分秒) 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())) //輸出堆棧信息 }
測(cè)試異常捕獲 main.go
package main import ( "fmt" "time" ) func main() { defer TryE() fmt.Println(time.Now()) panic(-2) fmt.Println("panic restore now, continue.") }
查看堆??梢远ㄎ籱ain 里第11行拋出異常-2.
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
go高并發(fā)時(shí)append方法偶現(xiàn)錯(cuò)誤解決分析
這篇文章主要為大家介紹了go高并發(fā)時(shí)append方法偶現(xiàn)錯(cuò)誤解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10golang實(shí)現(xiàn)對(duì)JavaScript代碼混淆
在Go語言中,你可以使用一些工具來混淆JavaScript代碼,一個(gè)常用的工具是Terser,它可以用于壓縮和混淆JavaScript代碼,你可以通過Go語言的`os/exec`包來調(diào)用Terser工具,本文給通過一個(gè)簡(jiǎn)單的示例給大家介紹一下,感興趣的朋友可以參考下2024-01-01golang控制結(jié)構(gòu)select機(jī)制及使用示例詳解
這篇文章主要介紹了golang控制結(jié)構(gòu)select機(jī)制及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10