xerrors 包是一個很是棒的設計,不一樣於往常語言如java/php,由於go的errors只是一個string類型的映射,因此內存佔用空間不多。這在golang的核心庫和golang大多數開源模塊中使用,簡單,高效,穩定!好比:php
var myErr:=errors.New("error msg") func act1()err{ return myErr }
以上代很是高效,若是你常常作go的開發時。這種解決時常常會存在一個很頭疼的問題,就是異常觸發點很難定位,由於你很難去定位到異常發生的代碼文件及行數和調用的堆棧,但出現問題時很是必要知道是什麼狀況處罰的這個異常,只是一個message不足以讓開發人員去解決問題。java
在最新的xerrors包中,引入了一個caller堆地址,經過使用Format接口能夠格式化出調用第一行的堆,但這每每不少時候不足以解決去定位問題。這時能夠考慮使用第三方包,請繼續往下看:)git
go.modgithub
require github.com/pkg/errors latest
go mod download
package main import( "fmt" "github.com/pkg/errors" ) func act1()error{ return errors.New("hello world!") } func main(){ fmt.Printf("%+v\n",act1()) }
Output:golang
Hello world!框架
main.act1異步
/tmp/aa/main.go:9函數
main.main性能
/tmp/aa/main.go:13ui
runtime.main
/usr/local/Cellar/go/1.13.4/libexec/src/runtime/proc.go:203
runtime.goexit
/usr/local/Cellar/go/1.13.4/libexec/src/runtime/asm_amd64.s:1357
以上代碼中,首先引用pkg/errrors堆異常包,而後經過使用%+v格式化error,將堆棧數據打印到屏幕中,經過這種方式,經過調用堆棧你能夠快速定位異常的代碼位置,從而快速解決問題。
glog是Golang log的縮寫,開源於golang核心庫,因此應用比較普遍實現以下:
package main import "log" func main(){ log.Println("Info","hello world") }
output:
2019/11/29 17:44:56 Info hello world
由於功能過於簡單,致使在golang中的日誌很難實現日誌的來源和日誌級別實現日誌的過濾功能。在不少模塊集成後,致使日誌繁雜錯亂很難閱讀,甚至到致不一樣模塊包括的日誌格式不一樣以及日誌的級別也不一致,致使日誌的分析帶來了很多挑戰!
midlog相似於java的slf4j框架,定義了通用的日誌級別、日誌來源鎖定、日誌重定向框架,而且提供日誌的重定義組件,能夠將全部日誌彙總處理,很是方便!
midlog 日誌框架示
go.mod
require github.com/lingdor/midlog
or
go get github.com/lingdor/midlog
建立日誌對象
var Logger Midlog = New("your module name")
建議這個Logger聲明爲外部可訪問的,這樣若是想實現日誌的分流時,能夠經過這個Logger對象判斷日誌的來源模塊是哪來的,而後分流不一樣的日誌記錄。
Logger.Trace("hello") Logger.Info("hello") Logger.Warn("hello") Logger.Debug("hello") Logger.Error1("hello") Logger.Error2("hello") Logger.Error3("hello") Logger.Log(LevelTrace, "hello") Logger.Infof("hello %s","world!") Logger.Tracef("hello %s","world!") Logger.Warnf("hello %s","world!") Logger.Debugf("hello %s","world!") Logger.Error1f("hello %s","world!") Logger.Error2f("hello %s","world!") Logger.Error3f("hello %s","world!") Logger.Logf(LevelTrace, "hello %s","world!")
能夠按照不一樣的日誌級別,選擇不一樣的函數,實現日誌的記錄!
go.mod 增長依賴
require github.com/lingdor/midlog v1.0.0 require github.com/lingdor/glog2midlog v1.0.0
package main import ( _ "github.com/lingdor/glog2midlog" "github.com/lingdor/midlog-examples/library1" "log" ) func main() { log.Println("info", "hello world!") }
output: \
2019-11-29 18:15:51 GLOG INFO hello world!
go.mod
require github.com/lingdor/midlog v1.0.0 require github.com/lingdor/midlog2logrus v1.4.3
main.go
package main import ( "fmt" "github.com/lingdor/midlog" _ "github.com/lingdor/midlog2logrus" ) var Logger = midlog.New("useLogrus") func main() { Logger.Info("hello world!") Logger.Error1("logger errror log") Logger.Ext(midlog.ExtMap{"123": "456"}).Error1("ext log") fmt.Println("done") }
output:
INFO[0000] hello world!
ERRO[0000] logger errror log
ERRO[0000] ext log 123=456
done
go.mod
require github.com/lingdor/midlog v1.0.0 require github.com/lingdor/midlog2zap v1.13.0
main.go
package main import ( "fmt" "github.com/lingdor/midlog" _ "github.com/lingdor/midlog2zap" ) var Logger = midlog.New("useLogrus") func main() { Logger.Info("hello world!") Logger.Error1("logger errror log") Logger.Ext(midlog.ExtMap{"123": "456"}).Info("ext log") fmt.Println("done") }
output:
{"level":"info","ts":1575022710.237491,"caller":"midlog2zap@v1.13.0/zapWriter.go:36","msg":"hello world!"}
{"level":"error","ts":1575022710.23755,"caller":"midlog2zap@v1.13.0/zapWriter.go:37","msg":"logger errror log","stacktrace":"github.com/lingdor/midlog2zap.ZapWriter.Write\n\t/Users/bobby96333/go/pkg/mod/github.com/lingdor/midlog2zap@v1.13.0/zapWriter.go:37\ngithub.com/lingdor/midlog.(*midlogT).tryWriteLog\n\t/Users/bobby96333/go/pkg/mod/github.com/lingdor/midlog@v1.0.0/logWriter.go:19\ngithub.com/lingdor/midlog.(*midlogT).logWithCaller3\n\t/Users/bobby96333/go/pkg/mod/github.com/lingdor/midlog@v1.0.0/midlog.go:122\ngithub.com/lingdor/midlog.(*midlogT).Error1\n\t/Users/bobby96333/go/pkg/mod/github.com/lingdor/midlog@v1.0.0/midlog.go:69\nmain.main\n\t/Users/bobby96333/go/midlog-examples/useZap/main.go:13\nruntime.main\n\t/usr/local/Cellar/go/1.13.4/libexec/src/runtime/proc.go:203"}
{"level":"info","ts":1575022710.237587,"caller":"midlog2zap@v1.13.0/zapWriter.go:36","msg":"ext log","123":"456"}
done
實際上midlog只是一個日誌接口層,並無實現日誌的滾動寫入、異步等日誌實際操做,但經過這個中間層,能夠靈活對接本身選擇的日誌框架,和分流功能。而後經過zap/logrus/seelog/zerolog等模塊組合實現日誌的存儲.
不論是go的原生error仍是log,都是一個很是棒的設計,不少時候能夠解決最基礎的需求,這避免了不少時候由於不須要而避免的額外性能消耗。而還有一部份場景,只是簡單每每不足以解決問題,這致使簡單和複雜的衝突哲學層面的取捨。咱們在選擇時,應該清楚瞭解本身的需求是什麼,按照本身的須要去選擇合適的模塊,便可!
謝謝