一、xerrors 异常

xerrors 包是一个很是棒的设计,不一样于往常语言如java/php,由于go的errors只是一个string类型的映射,因此内存占用空间不多。这在golang的核心库和golang大多数开源模块中使用,简单,高效,稳定!好比:php

        以上代很是高效,若是你常常作go的开发时。这种解决时常常会存在一个很头疼的问题,就是异常触发点很难定位,由于你很难去定位到异常发生的代码文件及行数和调用的堆栈,但出现问题时很是必要知道是什么状况处罚的这个异常,只是一个message不足以让开发人员去解决问题。java

        在最新的xerrors包中,引入了一个caller堆地址,经过使用Format接口能够格式化出调用第一行的堆,但这每每不少时候不足以解决去定位问题。这时能够考虑使用第三方包,请继续往下看:)git

二、堆栈异常处理

go.modgithub

 

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,将堆栈数据打印到屏幕中,经过这种方式,经过调用堆栈你能够快速定位异常的代码位置,从而快速解决问题。

 

三、go原生日志框架

      glog是Golang log的缩写,开源于golang核心库,因此应用比较普遍实现以下:

 

output:

2019/11/29 17:44:56 Info hello world

由于功能过于简单,致使在golang中的日志很难实现日志的来源和日志级别实现日志的过滤功能。在不少模块集成后,致使日志繁杂错乱很难阅读,甚至到致不一样模块包括的日志格式不一样以及日志的级别也不一致,致使日志的分析带来了很多挑战!

四、midlog 日志框架

midlog相似于java的slf4j框架,定义了通用的日志级别、日志来源锁定、日志重定向框架,而且提供日志的重定义组件,能够将全部日志汇总处理,很是方便! 

midlog 日志框架示 

4.一、midlog 包接取

go.mod

or

4.二、midlog通用日志函数

 建立日志对象

 建议这个Logger声明为外部可访问的,这样若是想实现日志的分流时,能够经过这个Logger对象判断日志的来源模块是哪来的,而后分流不一样的日志记录。

 

 

能够按照不一样的日志级别,选择不一样的函数,实现日志的记录!

 

4.三、对接go原生日志框架

go.mod 增长依赖

output: \

2019-11-29 18:15:51 GLOG INFO  hello world!

 

4.4 对接logrus

go.mod

main.go

output:

INFO[0000] hello world!                                 

ERRO[0000] logger errror log                            

ERRO[0000] ext log                                       123=456

done 

4.5 对接zap

go.mod

 main.go

 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,都是一个很是棒的设计,不少时候能够解决最基础的需求,这避免了不少时候由于不须要而避免的额外性能消耗。而还有一部份场景,只是简单每每不足以解决问题,这致使简单和复杂的冲突哲学层面的取舍。咱们在选择时,应该清楚了解本身的需求是什么,按照本身的须要去选择合适的模块,便可!

六、参考资料

谢谢