golang错误处理

每天一个俯卧撑 · · 2277 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

问题

错误处理,是非常重要的。在go语言中,错误处理被设计的十分简单。
如果做得好,会在排查问题等方面很有帮助;如果做得不好,就会比较麻烦。

从1.0开始,go中定义错误为 error 接口

// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
    Error() string
}

go语言中,错误处理的几种方式

  1. 通过判断值相等。像 io.EOF,go语言中,称为 sentinel error
  2. 通过断言( type assertion or type switch),判断err的类型或者是否实现了某个接口
  3. 利用包提供的方法。像 os.IsNotExist。go语言中,称为 ad-hoc check
  4. 当上面3中方式不可用时,通过搜索 err.Error() 是否包含特定字符串。(不被推荐)
  • 尽量不要使用 sentinel error
  • 尽量不要使用 ad-hoc check

错误值

go-grpc 中,定义错误值为:

message Status {
  // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
  int32 code = 1;

  // A developer-facing error message, which should be in English. Any
  // user-facing error message should be localized and sent in the
  // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
  string message = 2;

  // A list of messages that carry the error details.  There will be a
  // common set of message types for APIs to use.
  repeated google.protobuf.Any details = 3;
}

stack trace

在排查一个错误时,第一步通常是依据运行的流程,找到出错的地方,然后是看为什么出错。
这里,stack trace 对于查看问题有很大帮助。

而不是每个产生错误的地方都打印日志。先这样打日志比较费劲,查看问题的时候,也很难找到关键的信息。

凡是返回 error 的地方,返回一个合适的error。

关于性能
在业务开发中,并不需要可以关注这点。

message

在原有的错误 err.Error() 追加描述信息。这个一般是用来描述错误的原因。并产品级别提供给用户看的文案信息等同。这也意味着,在生产环境下,这个字段不应该对外展示(最好是,服务端不对外暴露)。

code

code 对应一种外部错误,和错误文案对应。(文案的多语言,在业务中间件中,统一依据 code + lang 获取文案信息)

details

如果在需要的情况下,增加details信息,暴露更多的错误细节。
details 尽量只用来排查信息,而不要用来逻辑判断。如果要用,采用 code

错误链

Unwarp

// Is reports whether err or any of the errors in its chain is equal to target.
func Is(err, target error) bool

// As checks whether err or any of the errors in its chain is a value of type E.
// If so, it returns the discovered value of type E, with ok set to true.
// If not, it returns the zero value of type E, with ok set to false.
func As(type E)(err error) (e E, ok bool)

上游,下游,本服务

正常流程正确,正常流程错误,异常流程,异常(nil)

  1. 正常流程正确,正常流程错误,异常流程错误

     正常流程正确,例如:签约接口,正常签约
     正常流程错误 同 外部错误,例如:验证手机验证码接口,用户输入错误验证码
     异常流程错误 同 内部错误,例如:解约接口,传递了一个不存在的签约号
    

错误值的序列化和反序列化 + format

所有地方都加,或者是外部包要Wrap一下

参考资料

https://go.googlesource.com/proposal/+/master/design/go2draft.md
https://godoc.org/golang.org/x/xerrors
https://github.com/pkg/errors 一个很好的包

备注

error consts.CaaError 同时存在,后者可以向前者赋值,可能出现混淆。所以,应该保持错误值的一致。

不要忽略错误。

  1. 错误处理

要显示,要能够从接口中表现出来。如果能够显示出具体有哪些错误,或者错误类型。throw 也要在函数,上做声明。error 显示返回

这个事实是很难的一件事情。代码分层不合理,基本是做不到的。相当于只应该在流程层(逻辑层或者service层)才能赋予错误码
保持一个service一个文件夹,一个接口一个文件


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:每天一个俯卧撑

查看原文:golang错误处理

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2277 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传