github.com/pkg/errors凭什么俘获一众开源项目的芳心

go标准库中的errors包实现标准error接口,实现上大简至道,error最终存储于string中,于是errorString进行一次包装,就完成了。但我这里不是针对errors包的描述,要从需求和应用角度进行细化的分析,errors包中的实现通用、直观且灵活,为什么这么说:

  • 作为error的容器,不能各种类型混杂,增加各种可能输入的处理,应对各种情况,这种事情很可能画蛇添足。我们需要的就是能装下所有需求的容器,这个容器就是string,这就是通用。
  • 直观是从需求角度出发,error一般输出在log中,传递给log库的东西一般是什么,string啊,string几乎可以是程序和人类交互的基础,什么信息都是通过string给出的,这里的string不特指字符串。所以我得到错误对象,第一步要干什么,提取string输出。
  • error等价于string这种思想非常灵活,string可以是任何形式,可以包含任何内容,所以灵活度相当高,作为最下层的库,灵活度可以说是第一原则,灵活度在这3点中最为重要,库的设计类似构建楼房,一层一层的搭建,下层的东西一定是与需求最远,但是有能包容需求的。

知道了errors的设计思路,那么问题是错误信息包含string并给上层api体现出这个string就完事了么,如果脱离使用场景,这么设计基本完全满足任何需求,但我们考虑下这个问题:工程师到底想从错误信息中得到什么?回答这个问题,我们得从最理想的结果往下走,逐步妥协给实现复杂度:

  • error信息不仅仅是一条log,要能给我程序运行的完整场景,这个场景让我身临其境般的无限次回溯当时场景,看到底是那个环节的逻辑出现问题。这么说可能比较难以想像,打个比方,《头号玩家》让你感觉到虚拟空间的真实感,脱离现实的不可能在这个世界也很easy的做到。理想的error展现,应该是多维度更加立体的展示,尽可能多的体现当时场景,让工程师迅速判断问题和解决方法,就跟电影一样,把现实中你所见到的code,日志抽象成更加容易接受立体的东西,更容易处理,你可以想想成一个空间,这个空间,能让你看到历史,程序在这个空间抽象成了其他东西,更能让人接受,类似对话。
  • 理想状态比较抽象,我自己也没有明确的概念图,但多维度这个事情是可以做到的,错误信息本身、错误发生的位置、促使错误发生的上下文这些都可以落实到日志中或者收集到存储中,并展现在某些后台上,工程师利用这些信息,了解、定位、最后解决问题。
  • 多维度需要收集大量信息,并需要有平台支持,增加工程师开发成本,很多公司并没有工具组,即便有可能也不会做的特别智能,因为想象力有限或者公司状态干扰。那么log中信息是否全面最为最原始的形态出现了,这种不要求工程师动消耗特别多脑力,简单打印发生处的一些上下文即可,人的因素占比比较大,问题也很可能因为人失误,无法查,但这个是性价比最高的方案,因为大部分业务场景都很简单,不需要有上面2点的情况,也能搞定。

github.com/pkg/errors 这个包我觉得是处于第二点和第三点之间,它给给error增加stack信息,允许整个函数调用链各层级在装饰error信息,通过丰富error信息的内容实现各种目的,这样是锦上添花的通常设计思路。这样各层级代码会更加耐看,否则,你要是想在出错后了解整个调用链,各层级打印log去吧,类似,代码还很难看。

致于具体源码,自己翻去吧,不能说简单,但还是希望有心的反复去看,反复去理解其中的设计思路。

github.com/pkg/errors凭什么俘获一众开源项目的芳心
Share this