跳过正文
  1. 文章/

grpc-go源码分析之logger

·2109 字·5 分钟
目录

从上个月开始梳理grpc-go的源码,希望从中学习到一些来自谷歌“原汁原味”的代码设计及风格。第一个开始分析的包是encoding,这个包下的代码行数不多,主要就是如下两个部分

  • encoding/decoding
  • compress/decompress

encoding/decoding是直接使用了第三方的包「<strong>protobuf</strong>规范的Go实现」,笔者没有继续深入梳理第三方包的代码。

compress/decompress是使用了Go SDK的compress包,笔者也并没继续往官方包的方向看代码。

所以对于grpc-go的encoding这个包,grpc-go本身并没有自己实现编码/解码,压缩/解压缩的代码,而是调用其他包。所以这个包也没什么代码值得去分析。不过值得一提的是笔者在看这个包的注释时候发现了一个错误,后来提了PR,reviewer当时跟我争辩了几句(他认为没有错)。然而,最终我的PR还是被合并啦!

接下来进入正题,开始分析第二个包grpclog。在梳理这个包的过程中,恰巧我准备从0开始为一个开源项目贡献Go-SDK。截止文章分享时,这个Go-SDK的logger部分我已经编写完成,设计的风格几乎与grpc的logger无异。毕竟,学以是为了致用 😀

通过源码可以知道loggerWrapper已经弃用,loggerT和tLogger是为了单元测试和基准测试用的,所以本文暂不讨论这三种struct(为行文流畅易读,struct在后面统称结构体)。

因此下文主要从以下三点分析:

  • glgger结构体
  • componentData结构体
  • 初始化流程

glogger结构体
#

梳理所有grpc-go打印日志的方法(除了测试用的实现方法)会发现:尽管一些方法所属的结构体并不是glogger(一些是下面的componentData),但调用链最终还是会到glogger结构体所属的方法。最后,glogger结构体的方法使用了第三方包“glog”输出日志。

glog是谷歌在github上开源的日志类项目

通过梳理这些结构体的实现方法,还能发现duck-typing这种设计思想在Go语言中的使用,深深体验到这种简洁的设计风格所带来的便利性。简单来说就是当一个结构体的实现了一个接口的所有方法,那么这个结构体就实现了这个接口。以grpc-go举例说明:

从下边的图可以看出glogger结构体实现了上边LoggerV2接口的所有方法,那么我们可以说glogger结构体实现了LoggerV2接口,而无需像Java一样在类后面显示地用implements声明。

componentData结构体
#

首先,可以从componentData结构体实现的方法看出:它同样了LoggerV2接口,如下图: