Errors before For 1.13

最简单的错误检查:

if err != nil {// sth went wrong
}

有事我们需要对sentinel error进行检查:

var ErrNotFound = errors.New(" not found")if err != ErrNotFound {// sth wasn‘t found
}

实现了error interface的自定义error struct,进行断言使用获取更丰富的上下文:

type NotFoundError struct {Name string
}func (e *NotFoundError) Error() string   {return e.Name + ": not found"
}if e, ok := err.(NotFoundError); ok {// e.Name wasn't found
}

函数在调用栈中添加信息向上传递错误,例如对错误发生时发生的情况的简要描述。

if err != nil {// 一旦用这种方式wrap了原始错误, 相当于原始错误(root error)丢失了 return fmt.Errorf(" decompress %v: %v", name, err)
}

使用创新错误fmt.Errorf丢弃原始错误中除文本外的所有内容。正如我们在上面的QueryError中看到的那样,我们有时可能需要定义一个包含底层错误的新错误类型,并将其保存以供代码检查。这里是QuertError

type QueryError struct {Query string     // 具体查询哪个地方报错了Err   error       // root error
}

程序可以查看QueryError值以根据底层错误作出决策。

if e, ok := err.(*QueryError);ok && e.Err == ErrPermission {// query failed because of a permission problem
}

go1.13为errorsfmt标准库包引入了新特性,以简化处理包含其他错误的错误。其中最为重要的点:包含另一个错误的error可以实现返回底层错误的Unwrap方法。如果e1.Uwrap()返回e2,那么我们说e1包装e2,我们可以展开e1来获取e2

按照此约定,我们可以为上面的QueryError指定一个Unwrap方法,该方法返回其包含的错误:

func (e *QueryError) Unwrap() error { return e.Err }

go1.13errors包包含两个用于检查错误的新函数:IsAs

// similar to
// if err == NotFound {...}
if errors.Is(err, ErrNotFound) {// sth wasn't found
}
// similar to
// if e, ok := err.(*QueryError);ok {...}
var e *QueryError
// Note: *QueryError is the type of error.
if errors.As(err, &e) {// err is a *QueryError, and e is set to the error's value
}
if errors.Is(err, ErrPermission) {// err, or some error that it wraps, is a permission problem
}

如前所述,使用fmt.Errorf向错误添加附加信息。

if err != nil {return fmt.Errorf(" decompress %v: %v", name, err)
}

在Go1.13中fmt.Errorf支持新的%w谓词。

if err != nil {// 用%w将错误包装起来// return an error which unwraps to errreturn fmt.Errorf(" decompress %v: %w", name, err)
}// %w内部实现
// 内部类似有个wrapError的结构体
type wrapError struct {msg stringerr error
}func (e *wrapError) Error() string {return e.msg
}func (e *wrapError) Unwrap() error {return e.err
}

%w包装错误可用于errors.Is以及errors.As

// ErrPerssion用%w进行包装
err := fmt.Errorf(" access denied: %w", ErrPerssion)
...
// 包装后可以用errors.Is进行判定
if errors.Is(err, ErrPermission) ...

go1.13 Is实现代码:

func Is(err, target error) bool {if target == nil {return err == nil}isComparable := reflectlite.TypeOf(target).Comparable()for {// 拿到根因错误够先去跟target对象比较,相等返回trueif isComparable && err == target {return true}// 先判定是否实现了Is方法if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {return true}// TODO: consider supporting target.Is(err). This would alow user-definable predicates, but// also may allow for coping with sloppy APIs, thereby making it easier to get away with them.// 若没有实现Is则不断取调用Unwrap方法取取到根因错误if err = Unwrap(err); err == nil {return false}}
}

Is方法也可以扩展:

假设我们知道有一些两个error(两个详细类型)判定是否相等,可以做一些自定义的逻辑:

type Error struct {Path stringUser string
}// 扩展Is方法
func (e *Error) Is(target error) bool {t, ok := target.(*Error)if !ok {return false}return (e.Path == t.Path || t.Path == "") && (e.User == t.User || t.User == "")
}if errors.Is(err, &Error{User: "someuser"}) {// err's User failed is "someuser".
}

errors & github.com/pkg/errors

pkg/errors目前兼容了errors的Is和As方法的:

package mainimport ("errors""fmt"xerrors "github.com/pkg/errors"
)var errMy = errors.New("my")func main() {err := test2()fmt.Printf("main: %+v\n", err)
}func test0() error {return xerrors.Wrapf(errMy, "test0 failed")      // 包含了堆栈信息
}func test1() error {return test0()
}func test2() error {return test1()
}// outPut:
main: my
test0 failed
main.test0../code/go/test/main.go:17
main.test1../code/go/test/main.go:21
main.test2../code/go/test/main.go:25
main.main../code/go/test/main.go:12
runtime.main../Go/src/runtime/proc.go:204
runtime.goexit../Go/src/runtime/asm_amd64.s:1374

References

https://www.infoq.cn/news/2012/11/go-error-handle/

https://golang.org/doc/faq#exceptions

https://www.ardanlabs.com/blog/2014/10/error-handling-in-go-part-i.html

https://www.ardanlabs.com/blog/2014/11/error-handling-in-go-part-ii.html

https://www.ardanlabs.com/blog/2017/05/design-philosophy-on-logging.html

https://medium.com/gett-engineering/error-handling-in-go-53b8a7112d04

https://medium.com/gett-engineering/error-handling-in-go-1-13-5ee6d1e0a55c

https://rauljordan.com/2020/07/06/why-go-error-handling-is-awesome.html

https://morsmachine.dk/error-handling

https://crawshaw.io/blog/xerrors

06 Errors For Go1.13相关推荐

  1. Go1.13:使用go mod 管理依赖, 提示cannot find module providing package或cannot find main module

    问题现象 编译go程序的时候报错: GOROOT=D:\go\GoSDK #gosetup GOPATH=D:\hc\workspace\fly\go\src\github.com\learngo;D ...

  2. 北京公交一卡通新用途:可拨打IC卡电话 2007年06月14日 13:53:13  来源:法制晚报

    北京公交一卡通(资料图片) 记者今天(14日)获悉,北京网通已经与市政交通一卡通达成协议,长安街沿线IC卡公用电话可使用"公交卡打电话"业务. 用户只需将一卡通放入IC卡电话的插卡 ...

  3. Go1.20 继续小修小补 errors 库。。。

    大家好,我是煎鱼. Go 的错误处理机制一直是无数人提了又争,被拒了又提的地方.最近 Go1.20 即将发布,针对 errors 标准库,有一个新的小修小补优化(wrapping multiple e ...

  4. 关于Go1.14,你一定想知道的性能提升与新特性

    作者:绘你一世倾城 链接:https://juejin.im/post/5e3f9990e51d4526cc3b1672 来源:掘金 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处 ...

  5. 正在或即将被使用的Go依赖包管理方法:Go Modules,Go 1.13的标准特性

    公众号原文地址:https://mp.weixin.qq.com/s/SGGV3tWEg5AAJ7I_FcK0cg 目录 目录 说明 初始化 依赖包的默认导入 依赖包的特定版本导入 查看已添加依赖 依 ...

  6. VMware Workstation 8下Ubuntu 13.04中安装VMware Tools出错

    vm 8.0上安装ubuntu 13.04系统以后,需要安装一个vm tool 方便屏幕适应和文件拷贝,但是发现由于ubuntu 13.04 使用的内核太新了,而vm8.0 不能够提供这样的文件,导致 ...

  7. go1.14基于信号的抢占式调度实现原理

    转载地址:http://xiaorui.cc/archives/6535 前言: 疫情期间里老老实实在家蹲着,这期间主要研究下go 1.14新增的部分.go 1.14中比较大的更新有信号的抢占调度.d ...

  8. go trace 剖析 go1.14 异步抢占式调度

    转载地址:https://mp.weixin.qq.com/s?__biz=MzAxMTA4Njc0OQ==&mid=2651441259&idx=2&sn=b57987e22 ...

  9. FastDFS V6.06 阿里云集群安装配置双IP(踩坑)

    安装之前 如果您看到了本教程请务必先阅读安装之前,看看是否是您期望的效果.可以利用FastDFS实现一个简单的对象存储功能. 实现效果 1.利用阿里云和腾讯云的3台学生主机 ECS 搭建一个分布式集群 ...

最新文章

  1. 动态规划和分治法,贪心算法以及递归的再一次深刻理解和体会
  2. php什么版本好玩_新区传奇世界手游10点准时开放丨两个版本
  3. What is ieHTTPHeaders?
  4. python矩阵旋转函数_Python3算法之十:矩阵旋转
  5. 如何理解“不要通过共享内存来通信,而应该通过通信来共享内存”?
  6. vb 实现小超市饮料补货提醒程序 public全局变量的声明与初始化
  7. 垃圾邮件分类器_如何在10个步骤中构建垃圾邮件分类器
  8. Bootstrap定制开发
  9. word2vector数据集样式_这样做数据可视化驾驶舱,高端大气,一目了然,领导不点赞都难...
  10. vcenter server 许可证_朝阳互联网信息服务许可证ICP内资新办时间找杜经理
  11. 28天打造专业红客(四)
  12. Vue, element-ui Module build failed: Error: No PostCSS Config found
  13. 阿里ai人工智能平台_AI标签众包平台
  14. 自定义Qml控件:ImageButton
  15. 简简单单 谁说雅虎助手卸载不掉(转)
  16. 2021年人工智能学习路线图分享
  17. python爬裁判文书网_对爬取中国裁判文书网的分析
  18. 程序员职业生涯系列:关于技术能力的思考与总结
  19. zbox mysql_centos6.5搭建禅道
  20. 如何实现视频平台会员多账号登录

热门文章

  1. step5 lasso 回归 实战 本文没有考虑y 是cox和binominal
  2. 设计模式(10)[JS版]-JavaScript如何实现组合模式???
  3. HBase与Hadoop生态其他组件的联系
  4. 求n的阶乘,求1~n的阶乘和(循环)
  5. Glassfish JAVA容器中间件使用(咋个办呢 zgbn)
  6. 关于vue中采用scoped时,组件的中css优先级
  7. 【Java】JDK目录介绍
  8. srand rand RAND_MAX
  9. Redis(上)基础及8种数据类型
  10. 51单片机入门之五:数码管显示(动态),单片机驱动数码