Go 1.13 errors 基本用法

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

Go 最新版本 1.13 中新增了 errors 的一些特性,有助于我们更优雅的处理业务逻辑中报错的问题。
本文主要展示 errors 包中新增方法的用法。

核心思想:套娃

啥意思呢?这玩意就像套娃一样,从上往下扒,拿走一个还有一个,再拿走一个,诶还有一个,如果你愿意,可以一直扒到最底下没有了为止。

基本用法

1. 创建一个被包装的 error

方式一:fmt.Errorf

使用 %w 参数返回一个被包装的 error

err1 := errors.New("new error")
err2 := fmt.Errorf("err2: [%w]", err1)
err3 := fmt.Errorf("err3: [%w]", err2)
fmt.Println(err3)
// output
err3: [err2: [new error]]

err2 就是一个合法的被包装的 error,同样地,err3 也是一个被包装的 error,如此可以一直套下去。

方式二:自定义 struct

type WarpError struct {
    msg string
    err error
}

func (e *WarpError) Error() string {
    return e.msg
}

func (e *WrapError) Unwrap() error {
    return e.err
}

之前看过源码的同学可能已经知道了,这就是 fmt/errors.go 中关于 warp 的结构。
就,很简单。自定义一个实现了 Unwrap 方法的 struct 就可以了。

2. 拆开一个被包装的 error

errors.Unwrap

err1 := errors.New("new error")
err2 := fmt.Errorf("err2: [%w]", err1)
err3 := fmt.Errorf("err3: [%w]", err2)

fmt.Println(errors.Unwrap(err3))
fmt.Println(errors.Unwrap(errors.Unwrap(err3)))
// output
err2: [new error]
new error

3. 判断被包装的 error 是否是包含指定错误

errors.Is

当多层调用返回的错误被一次次地包装起来,我们在调用链上游拿到的错误如何判断是否是底层的某个错误呢?
它递归调用 Unwrap 并判断每一层的 err 是否相等,如果有任何一层 err 和传入的目标错误相等,则返回 true。

err1 := errors.New("new error")
err2 := fmt.Errorf("err2: [%w]", err1)
err3 := fmt.Errorf("err3: [%w]", err2)

fmt.Println(errors.Is(err3, err2))
fmt.Println(errors.Is(err3, err1))
// output
true
true

4. 提取指定类型的错误

errors.As

这个和上面的 errors.Is 大体上是一样的,区别在于 Is 是严格判断相等,即两个 error 是否相等。
As 则是判断类型是否相同,并提取第一个符合目标类型的错误,用来统一处理某一类错误。

type ErrorString struct {
    s string
}

func (e *ErrorString) Error() string {
    return e.s
}

var targetErr *ErrorString
err := fmt.Errorf("new error:[%w]", &ErrorString{s:"target err"})
fmt.Println(errors.As(err, &targetErr))
// output
true

扩展

Is As 两个方法已经预留了口子,可以由自定义的 error struct 实现并覆盖调用。

源码也没什么可说的,太简单了,一眼就能看懂的。

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

本文来自:Segmentfault

感谢作者:sxssxs

查看原文:Go 1.13 errors 基本用法

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

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