基于石墨文档基于K8S的Go微服务实践,我们这次把该内容中的错误码做了一个详细的介绍。
0 背景
我们内部系统全部统一采用gRPC
协议和protobuf
编解码。统一的好处在于不需要在做任何协议、编解码转换,这样就可以使我们所有业务采用同一个protobuf
仓库,基于CI/CD
工具实现许多自动化功能。
我们要求所有服务提供者提前在独立的路径下定义好接口和错误码的protobuf
文件,然后提交到GitLab
,我们通过GitLab CI
的check
阶段对变更的protobuf
文件做format
、lint
、breaking
检查。然后在build
阶段,会基于protobuf
文件中的注释自动产生文档,并推送至内部的微服务管理系统接口平台中,还会根据protobuf
文件自动构建Go/PHP/Node/Java
等多种语言的桩代码和错误码,并推送到指定对应的中心化仓库。推送到仓库后,我们就可以通过各语言的包管理工具拉取客户端、服务端的gRPC和错误码的依赖,不需要口头约定对接数据的定义,也不需要通过IM
工具传递对接数据的定义文件,极大的简化了对接成本。
1 判断Error的错误原理
要了解怎么处理gRPC
的error
之前,我们首先来看下Go
普通的error
是怎么处理的。
我们在判断一个error
的根因,需要根因error
是一个固定地址的指针类型,这样我们才能够使用官方的errors.Is
方法判断他是否为根因。以下是一个代码示例:
我们先看这个代码errors.Is(wrapNewPointerError(), fmt.Errorf("i am error"))
的执行步骤,首先构造了一个error
,然后使用官方%w
的方式将error
进行了包装,我们在使用errors.Is
方法判断的时候,底层函数会将error
解包来判断两个error
的地址是否一致。
因此我们第一个errors.Is
执行的是个false
。在使用这个代码errors.Is(wrapConstantPointerError(), sentinelErr)
,因为是固定地址的error