06 Errors For Go1.13
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为errors
和fmt
标准库包引入了新特性,以简化处理包含其他错误的错误。其中最为重要的点:包含另一个错误的error
可以实现返回底层错误的Unwrap
方法。如果e1.Uwrap()
返回e2
,那么我们说e1
包装e2
,我们可以展开e1
来获取e2
。
按照此约定,我们可以为上面的QueryError
指定一个Unwrap
方法,该方法返回其包含的错误:
func (e *QueryError) Unwrap() error { return e.Err }
go1.13errors
包包含两个用于检查错误的新函数:Is
和As
。
// 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相关推荐
- 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 ...
- 北京公交一卡通新用途:可拨打IC卡电话 2007年06月14日 13:53:13 来源:法制晚报
北京公交一卡通(资料图片) 记者今天(14日)获悉,北京网通已经与市政交通一卡通达成协议,长安街沿线IC卡公用电话可使用"公交卡打电话"业务. 用户只需将一卡通放入IC卡电话的插卡 ...
- Go1.20 继续小修小补 errors 库。。。
大家好,我是煎鱼. Go 的错误处理机制一直是无数人提了又争,被拒了又提的地方.最近 Go1.20 即将发布,针对 errors 标准库,有一个新的小修小补优化(wrapping multiple e ...
- 关于Go1.14,你一定想知道的性能提升与新特性
作者:绘你一世倾城 链接:https://juejin.im/post/5e3f9990e51d4526cc3b1672 来源:掘金 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处 ...
- 正在或即将被使用的Go依赖包管理方法:Go Modules,Go 1.13的标准特性
公众号原文地址:https://mp.weixin.qq.com/s/SGGV3tWEg5AAJ7I_FcK0cg 目录 目录 说明 初始化 依赖包的默认导入 依赖包的特定版本导入 查看已添加依赖 依 ...
- VMware Workstation 8下Ubuntu 13.04中安装VMware Tools出错
vm 8.0上安装ubuntu 13.04系统以后,需要安装一个vm tool 方便屏幕适应和文件拷贝,但是发现由于ubuntu 13.04 使用的内核太新了,而vm8.0 不能够提供这样的文件,导致 ...
- go1.14基于信号的抢占式调度实现原理
转载地址:http://xiaorui.cc/archives/6535 前言: 疫情期间里老老实实在家蹲着,这期间主要研究下go 1.14新增的部分.go 1.14中比较大的更新有信号的抢占调度.d ...
- go trace 剖析 go1.14 异步抢占式调度
转载地址:https://mp.weixin.qq.com/s?__biz=MzAxMTA4Njc0OQ==&mid=2651441259&idx=2&sn=b57987e22 ...
- FastDFS V6.06 阿里云集群安装配置双IP(踩坑)
安装之前 如果您看到了本教程请务必先阅读安装之前,看看是否是您期望的效果.可以利用FastDFS实现一个简单的对象存储功能. 实现效果 1.利用阿里云和腾讯云的3台学生主机 ECS 搭建一个分布式集群 ...
最新文章
- 动态规划和分治法,贪心算法以及递归的再一次深刻理解和体会
- php什么版本好玩_新区传奇世界手游10点准时开放丨两个版本
- What is ieHTTPHeaders?
- python矩阵旋转函数_Python3算法之十:矩阵旋转
- 如何理解“不要通过共享内存来通信,而应该通过通信来共享内存”?
- vb 实现小超市饮料补货提醒程序 public全局变量的声明与初始化
- 垃圾邮件分类器_如何在10个步骤中构建垃圾邮件分类器
- Bootstrap定制开发
- word2vector数据集样式_这样做数据可视化驾驶舱,高端大气,一目了然,领导不点赞都难...
- vcenter server 许可证_朝阳互联网信息服务许可证ICP内资新办时间找杜经理
- 28天打造专业红客(四)
- Vue, element-ui Module build failed: Error: No PostCSS Config found
- 阿里ai人工智能平台_AI标签众包平台
- 自定义Qml控件:ImageButton
- 简简单单 谁说雅虎助手卸载不掉(转)
- 2021年人工智能学习路线图分享
- python爬裁判文书网_对爬取中国裁判文书网的分析
- 程序员职业生涯系列:关于技术能力的思考与总结
- zbox mysql_centos6.5搭建禅道
- 如何实现视频平台会员多账号登录