每日快播:GO 1.20 新功能:多重错误包装

2022-12-27 14:20:22

预计将于 2023 年 2 月发布的 Go 1.20 有一个小的变化,对于那些大量使用错误包装的应用程序来说,可能会有效改进它们的错误处理方法。


【资料图】

让我们看一下它的用法,但首先,需要简要回顾一下什么是错误包装。如果你已经掌握了可以直接跳到下面的 “Go 1.20 新功能” 部分以获取新的信息。

Go 中的错误是实现一个非常简单的接口:

typeerrorinterface{Error()string}

错误类型可以是任何东西,从string本身到int,但通常它们是struct类型。下面这个例子来自标准库:

typeerrstruct{sstring}func(e*err)Error()string{returne.s}

要检查 Go 中的错误,你只需比较一个值(在本例中为int值):

iferr==io.EOF{//...}

第二种常见的用法是检查错误的类型,那也意味着要写更多的代码:

ifnerr,ok:=err.(net.Error){//...(usenerrwhichisanet.Error)}

在上面的例子中,类型断言测试类型net.Error的err值,并创建一个新变量nerr,它可以在 if 语句中使用。Go 中的错误方便理解、易于使用且非常高效。

错误包装

从 Go 1.13 开始,引入了错误包装。包装允许将错误嵌入到其他错误中,就像在其他语言中包装异常一样。这非常实用,比如函数遇到 “record not found” 错误时,可以向错误信息中添加更多上下文信息,例如 “unknown user: record not found”。

Go 中错误包装设计背后的有趣想法是:契约不用关心错误类型、结构或它们是如何创建的。而唯一关注的是解包过程和转换为字符串,因为这两者是必须的。这就非常容易实现:支持解包的错误类型必须实现Unwrap() error方法。

标准库中没有(命名的)接口可以向您展示,因为接口是隐式实现的,没有必要单独写一个。这里我们写一个只是为了更好说明这篇文章:

typeWrappedErrorinterface{Unwrap()error}

我们来看看 Go 标准库(实际上是 package fmt)中是如何实现包装错误的:

typewrapErrorstruct{msgstringerrerror}func(e*wrapError)Error()string{returne.msg}func(e*wrapError)Unwrap()error{returne.err}

由于上面错误类型实现了Error() string方法,所以说 Go 中的错误实际上最终是字符串并没有错,因此需要一种创建这些字符串的良好机制。这就是标准库中的函数fmt.Errorf发挥作用的地方:

varRecordNotFoundErr=errors.New("notfound")constname,id="lzap",13werr:=fmt.Errorf("unknownuser%q(id%d):%w",name,id,recordNotFoundErr)fmt.Println(werr.Error())

一个特殊格式的动词%w,每次调用只能使用一次(稍后会详细介绍),用于错误参数。除此之外,该函数的工作方式类似于fmt.Printf函数。下面的例子打印了这个结果:

unknownuser"lzap"(id13):notfound

如你所见,错误包装本质上是一个链表。要解包错误,请使用errors.Unwrap函数,该函数将为链表中的最后一个错误值返回nil。要检查错误类型或值,需要遍历整个列表,这对于需要进行频繁的错误检查不太实用。幸运的是,有两个辅助函数可以做到这一点。

检查包装错误列表中的值:

iferrors.Is(err,RecordNotFoundErr){//...}

检查特定类型(下面例子是来自标准库的网络错误):

varnerr*net.Erroriferrors.As(err,&nerr){//...(usenerrwhichisa*net.Error)}

以上总结了 Go 1.13 及更高版本中的错误包装。

Go 1.20 新特性

让我们看看 Go 1.20 中真正的新功能,从函数errors.Join开始,它通过可变参数包装错误列表:

err1:=errors.New("err1")err2:=errors.New("err2")err:=errors.Join(err1,err2)fmt.Println(err)

当事先不知道错误数量时,此功能可用于将错误连接在一起。一个很好的例子是从 goroutines 收集错误。值得一提的是,该函数将列表中的错误与换行符连接起来。上面的代码片段打印:

err1err2

对于许多应用程序或(日志记录)库来说,这可能会存在问题,它们期望错误通常只是没有换行符的字符串。幸运的是,Go 1.20 中的另一个变化改变了fmt.Errorf的行为:该函数现在接受多个%w格式说明符:

err1:=errors.New("err1")err2:=errors.New("err2")err:=fmt.Errorf("%w+%w",err1,err2)fmt.Println(err)

以前会导致格式错误的格式字符串现在可以正确打印:

err1+err2

同时包装多个错误实现Unwrap() error,这是可能的吗?

事实证明,在 Go 1.20 标准库中有一种新的机制: 实现Unwrap() []error函数的错误类型可以包装多个错误。让我们来看看这是如何在库中实现的:

typejoinErrorstruct{errs[]error}func(e*joinError)Error()string{//concatenateerrorswithanewlinecharacter}func(e*joinError)Unwrap()[]error{returne.errs}

一个理论上的接口,但标准库中实际不存在,如下所示:

typeMultiWrappedErrorinterface{Unwrap()[]error}

由于 Go 不允许方法重载,因此每种类型都可以实现Unwrap() error或Unwrap() []error,但不能同时实现。还记得我提到过包装错误本质上是一个链表吗?实现前一个(新引入的)方法的类型实际上形成了一个链接树,函数errors.Is和errors.As的工作方式相同,只是现在它们需要遍历树而不是列表。根据文档,该实现执行预排序、深度优先遍历。

这确实是 Go 1.20 带来的全部,它可能看起来是一个小的变化,但它提供了如何有效和干净地处理错误的新方法。在展示真实示例之前,让我总结一下新功能:

新的Unwrap []error函数契约允许遍历错误树。

新的errors.Join函数,这是一个方便的函数,用于连接两个错误字符串值(使用换行符)。

现有函数errors.Is和errors.As已更新,可以同时处理错误列表和错误树。

现有函数fmt.Errorf现在接受多个%w格式动词。实践

上面这一切都很棒,但是你如何在实践中利用它呢?

在一个小型 REST API 微服务中,我们通过errors.New和fmt.Errorf处理来自 DAO 包(数据库)、REST 客户端(其他后端服务)和其他包的各种错误。返回的 HTTP 状态代码应该是 2xx、4xx 或 5xx,具体取决于错误状态以遵循最佳 REST API 实践。实现此过程的一种方法是解开主 HTTP 处理程序中的错误并找出它是哪种错误。

然而,通过多重错误包装,现在可以包装根本原因(例如数据库返回 “no records found” )和返回给用户 HTTP 代码(在本例中为 404)。

一个工作示例如下所示:

packagemainimport("errors""fmt")//commonHTTPstatuscodesvarNotFoundHTTPCode=errors.New("404")varUnauthorizedHTTPCode=errors.New("401")//databaseerrorsvarRecordNotFoundErr=errors.New("DB:recordnotfound")varAffectedRecordsMismatchErr=errors.New("DB:affectedrecordsmismatch")//HTTPclienterrorsvarResourceNotFoundErr=errors.New("HTTPclient:resourcenotfound")varResourceUnauthorizedErr=errors.New("HTTPclient:unauthorized")//applicationerrors(thenewfeature)varUserNotFoundErr=fmt.Errorf("usernotfound:%w(%w)",RecordNotFoundErr,NotFoundHTTPCode)varOtherResourceUnauthorizedErr=fmt.Errorf("unauthorizedcall:%w(%w)",ResourceUnauthorizedErr,UnauthorizedHTTPCode)funchandleError(errerror){iferrors.Is(err,NotFoundHTTPCode){fmt.Println("Willreturn404")}elseiferrors.Is(err,UnauthorizedHTTPCode){fmt.Println("Willreturn401")}else{fmt.Println("Willreturn500")}fmt.Println(err.Error())}funcmain(){handleError(UserNotFoundErr)handleError(OtherResourceUnauthorizedErr)}

这将打印:

Willreturn404usernotfound:DB:recordnotfound(404)Willreturn401unauthorizedtocallotherservice:HTTPclient:unauthorized(401)

从这样的人工代码片段中可能看起来不太明显的是,实际上的错误声明通常分布在许多包中,并且不容易跟踪所有可能的错误以确保所需的 HTTP 状态代码。在这种方法中,所有在一个地方声明的应用程序级包装错误也包含了 HTTP 代码。

请注意,这在 Go 1.19 或更早版本中是不可能的,因为fmt.Errorf函数只会包装第一个错误。该代码确实在 1.19 上可以编译,甚至不会产生运行时恐慌,但它实际上不会工作。

显然,常见的 HTTP 状态代码很容易成为一种新的错误类型(基于int类型),因此可以通过errors.As轻松提取实际代码,但我想让示例保持简单。

Feel free to play around with the code on Go Playground. Make sure to use “dev branch” or 1.20+ version of Go. 可以在 Go Playground 上自由运行上述代码。确保使用 “dev branch” 或 Go 的 1.20+ 版本。现有应用

在你的应用程序中实施新功能时,请注意errors.Unwrap函数。对于具有Unwrap() []error的错误类型,它总是返回nil:

err1:=errors.New("err1")err2:=errors.New("err2")err:=errors.Join(err1,err2)unwrapped:=errors.Unwrap(err)fmt.Println(unwrapped)

由于 Go 1.X 兼容性承诺,这会打印出 “nil”。当你引入多个包装错误时,请确保检查展开代码。幸运的是,典型 Go 代码中的大部分错误检查都是使用errors.Is和errors.As完成的。

错误包装并不是 Go 中所有错误处理的最终解决方案。它只是提供了一种干净的方法来处理典型 Go 应用程序中的错误,对于简单应用程序来说也许就完全足够了。原文地址:https://lukas.zapletalovi.com/posts/2022/wrapping-multiple-errors/原文作者:Lukáš Zapletal本文永久链接:https://github.com/gocn/translator/blob/master/2022/w50_Wrapping_multiple_errors译者:haoheipi

校对:watermelo

往期推荐

谷歌发布查找开源漏洞的Go工具OSV-Scanner

最好的Go框架:没有框架?

「每周译Go」如何在Go中构造For 循环

想要了解Go更多内容,欢迎扫描下方关注公众号,回复关键词 [实战群],就有机会进群和我们进行交流

分享、在看与点赞Go

标签:

岳阳市生态环境局召开落实省委第七巡视组巡视岳阳反馈意见整改调度会

红网时刻岳阳9月9日讯(通讯员王嵘)为认真贯彻落实省委、省委巡视组及

09-09 13:14:41

广深城际9日停运56趟列车

每经AI快讯,9月8日,受深圳地区持续强降雨天气影响,深圳火车站(罗湖

09-09 11:36:08

历时172天!宁夏引黄灌区2023年夏秋灌圆满收官

扬水系统开足马力保灌溉。9月8日15时,随着沙坡头北干渠进水闸关闭,我

09-09 09:53:14

“儿子”超岛被指售“假羊肉”,当“爹”的巴奴冤吗?

来源|雷达财经作者|孟帅频频被爆出各种乱象的餐饮赛道,又有新事发生

09-09 08:10:23

用益-金融市场观察:沪指涨逾1% 北向资金净买入近70亿元

股市:A股收涨沪指涨逾1%北向资金净买入近70亿元9月4日A股三大指数今日

09-09 05:47:17

美国男篮不敌德国男篮,无缘世界杯决赛

美国男篮不敌德国男篮,无缘世界杯决赛---9月8日晚,在2023国际篮联男

09-09 01:01:41

狙击龙虎榜:华为行情扩散!星闪、中国版星链热度升温

卫星互联网概念股一览!详情

09-08 21:49:09

麦迪逊:勇敢不只是去飞身铲球或大喊大叫,而是勇于去拿球和争抢

直播吧9月8日讯近日,热刺中场麦迪逊接受了《泰晤士报》的专访。谈到自

09-08 20:35:44

揭秘涨停|龙头获超46万手封死涨停,这一概念持续被引爆

9月8日,A股市场共45股涨停(包含8只ST股)。另外,14股封板未遂,整体

09-08 18:20:01

《金融稳定法》列入立法规划 金融稳定保障基金呼之欲出

金融安全是国家经济社会健康平稳运行的重要前提和基础,事关国家根本利

09-08 17:06:09

30万以内最强五座SUV,新岚图FREE没有套路,全是诚意!

“买大品牌生产的东西,一定没问题。”相信无论是在选购一些小物件还是

09-08 16:08:14

东北一垧地是多少亩?

垧,土地面积单位,是东北地区的民间俗称,约等于15亩地,其标称为公顷

09-08 15:10:50

异佛尔酮二异氰酸酯 IPDI商品报价动态(2023-09-08)

交易商品牌 产地交货地最新报价异佛尔酮二异氰酸酯 ≥99 5%济南洪旺化

09-08 13:53:48

10万册图书免费读!书香河南公共文化平台正式上线

整合作家大咖的新书发布、阅读分享及文化讲座等线上阅读活动,积极营造

09-08 12:22:25

美企将迎违约倒闭潮 “宽松货币”时代一去不复返!亿万富翁投资者、橡树资本管理公司(Oaktree Capital Management)联合创始人霍华德•马克斯(Howard Marks)日前表示,美国更多企业将感受到美联储抗击通胀的全面影响,并将陷入违约

美企将迎违约倒闭潮“宽松货币”时代一去不复返!亿万富翁投资者、橡树

09-08 11:20:56

南关区委常委、副区长魏东走访科技创新产业链企业

近日,区委常委、副区长魏东利用一周左右时间到企业、院所、运营公司、

09-08 10:29:28

​天镇县举行全县重点项目推进会

黄河新闻网大同讯(记者魏悦)近日,大同市天镇县在办公楼三楼常委会议

09-08 09:38:58

伟测科技:8月31日融券净卖出2.6万股,连续3日累计净卖出21.32万股

8月31日,伟测科技(688372)融资买入4605 17万元,融资偿还3714 44万

09-01 10:14:56

棕榈油 需求端带来提振

近期,豆类整体走势偏强,而油脂走势相对偏弱。不过,8月15日,油脂拉

09-01 09:36:52

科华数据:光储发力业绩释放 算力服务未来可期

8月30日晚间,科华数据(002335)发布2023年半年度报告,上半年公司实现

09-01 08:59:06

被拦截的短信在哪里可以看到

被拦截的短信在哪里可以看到,以华为手机为例,被拦截的短信在短信界面

09-01 07:17:51

天机沉睡之城有声小说 天机1沉睡之城蔡骏

1、如果回答了,会被正在看小说但还没看完的广大读者们痛扁的。2、给个

09-01 05:19:35

Switch 2秘密噱头或泄露:AR图像传感器相机

关于Switch2的新传言表明,其主要卖点之一涉及内置摄像头,尽管目前尚

09-01 00:07:40

美智库:美国滥用制裁 会阻碍缔造和平的努力

海外网8月31日电美国智库“昆西国家事务研究所”8月29日发文,援引当天

08-31 21:50:04

2023年服贸会文旅服务专题展主打数字化体验

中国青年报客户端讯(中青报·中青网记者张敏)2023年服贸会期间,文旅

08-31 19:54:27

祥鑫科技:公司间接为问界汽车供应相关部件产品

祥鑫科技(002965)表示,公司为问界汽车间接提供相关部件产品。在新能源

08-31 18:40:14

NCT组合将出演音乐节目 带来《Baggy Jeans》舞台

NCT组合将出演音乐节目带来《BaggyJeans》舞台

08-31 17:24:10

海昌新材(300885)龙虎榜数据(08-31)

沪深交易所2023年08月31日公布的交易公开信息显示,海昌新材因成为有价

08-31 16:09:22

怎样酿造葡萄酒 酿造葡萄酒的方法

hello大家好,我是城乡经济网小晟来为大家解答以上问题,怎样酿造葡萄

08-31 15:00:29

曝《巫师4》开发团队扩至250人

波兰游戏开发商CDProjekt在最近的季度财务报告中确认,其正在开发的下

08-31 14:03:12

青海开学第一课观后感写作辅导(附直播入口)

青海开学第一课在哪个平台看直播时间2023年9月1日(周五)晚20:00直播 回

08-31 12:21:29

你是电你是光你是唯一的神话这首歌叫什么名字 你是电你是光你是唯一的神话

1、superstar。相信通过你是电你是光你是唯一的神话这篇文章能帮到你,

08-31 11:09:08

国泰君安:地产政策优化 影响几何?

国泰君安:地产政策优化影响几何?,限购,认贷,首付比例,房贷利率,地产

08-31 10:01:49

7月PCE数据或小幅回升,美联储内部分歧何时休?

7月PCE数据或小幅回升,美联储内部分歧何时休?,加息,pce,美联储政策,

08-31 09:14:23

开学季来了!这些路段注意避开!

要!开!学!啦!大家最害怕的一定是开学堵车吧小福特意做了份2023年深

08-31 08:16:41

柳州确诊新冠肺炎的孕妇还能母乳喂养吗

在新冠肺炎疫情肆虐的情况下,准妈妈们是不是在担心自己和宝宝的安全呢

08-31 06:14:34

基于股价处于低位 万科决定终止A股定增事项

新京报讯(记者段文平)8月30日晚,万科发布公告称,公司于2023年8月30日

08-31 02:38:36

津门虎无缘足协杯四强 “浪费机会必遭惩罚”果然是足球场上的真理

2021赛季,津门虎就曾以0:2的比分败在大连人的脚下,被挡在了足协杯8

08-30 22:19:14

美军仓皇撤离阿富汗两周年丨美国撤军留下烂摊子 伤痛仍未远离阿富汗

两年前的今天,也就是2021年8月30日,随着最后一架美军运输机从喀布

08-30 20:52:01

拉萨会是西部的下一个时尚中心吗?

根据联商网报道,拉萨王府井购物中心将在2023年年底正式投入运营,选址

08-30 19:35:51

受台风影响,潮州全市中小学校、中职学校、幼儿园开学时间调整为 9月4日

8月30日下午,潮州市教育局发布通知,将潮州全市普通中小学校、中职学

08-30 18:08:37

增值税发票怎么开步骤ukey(增值税发票怎么开步骤)

1、现今营业税改增值税,剪口发票已经不能使用了,企业只能开具机打的

08-30 16:59:42

大冒险游戏问题大全(大冒险游戏问题)

导读1、跳脱衣舞当众呦。本文到此讲解完毕了,希望对大家有帮助。免责

08-30 16:02:48

韩国政府联合三星电子、SK海力士等开发半导体先进封装技术

《科创板日报》30日讯,韩国产业通商资源部(MOTIE)8月29日宣布,将与

08-30 14:49:19

看电视现在是一种比较高级的视听享受

【本文来自《从“万人迷”到“万人嫌”:销量创十年来最差,我们离电视

08-30 13:35:56

新疆女生收到西安网友免费寄的特产

00:518月25日,新疆伊犁。马女士收到了一箱来自一位素未谋面的西安网友

08-30 12:08:25

石头科技发布自清洁机器人P10系列:6000Pa的吸力,扫拖联动智能避障

石头科技是一家专注于家庭智能清洁领域的品牌,自2017年推出首款清洁产

08-30 10:51:43

沙特主权财富基金旗下的的油气钻探公司ADES计划在沙特交易所进行IPO

沙特主权财富基金(PIF)旗下的的油气钻探公司ADES控股公司周一宣布,计

08-30 09:47:46

提高综合保税区高质量发展“含金量”

提高综合保税区高质量发展“含金量”---综合保税区是推进高水平对外开

08-30 08:55:31

近两月沪深交易所零受理 A股IPO节奏或已按下“放缓键”

来源:上海证券报Choice数据显示,7月沪深交易所合计21家企业上会,8月

08-30 07:53:01

广深城际9日停运56趟列车
历时172天!宁夏引黄灌区2023年夏秋灌圆满收官
“儿子”超岛被指售“假羊肉”,当“爹”的巴奴冤吗?
用益-金融市场观察:沪指涨逾1% 北向资金净买入近70亿元
美国男篮不敌德国男篮,无缘世界杯决赛
狙击龙虎榜:华为行情扩散!星闪、中国版星链热度升温
麦迪逊:勇敢不只是去飞身铲球或大喊大叫,而是勇于去拿球和争抢
揭秘涨停|龙头获超46万手封死涨停,这一概念持续被引爆
《金融稳定法》列入立法规划 金融稳定保障基金呼之欲出
30万以内最强五座SUV,新岚图FREE没有套路,全是诚意!
东北一垧地是多少亩?
异佛尔酮二异氰酸酯 IPDI商品报价动态(2023-09-08)
10万册图书免费读!书香河南公共文化平台正式上线
美企将迎违约倒闭潮 “宽松货币”时代一去不复返!亿万富翁投资者、橡树资本管理公司(Oaktree Capital Management)联合创始人霍华德•马克斯(Howard Marks)日前表示,美国更多企业将感受到美联储抗击通胀的全面影响,并将陷入违约
南关区委常委、副区长魏东走访科技创新产业链企业
​天镇县举行全县重点项目推进会
伟测科技:8月31日融券净卖出2.6万股,连续3日累计净卖出21.32万股
棕榈油 需求端带来提振
科华数据:光储发力业绩释放 算力服务未来可期
被拦截的短信在哪里可以看到
天机沉睡之城有声小说 天机1沉睡之城蔡骏
Switch 2秘密噱头或泄露:AR图像传感器相机
美智库:美国滥用制裁 会阻碍缔造和平的努力
2023年服贸会文旅服务专题展主打数字化体验
祥鑫科技:公司间接为问界汽车供应相关部件产品
NCT组合将出演音乐节目 带来《Baggy Jeans》舞台
海昌新材(300885)龙虎榜数据(08-31)
怎样酿造葡萄酒 酿造葡萄酒的方法
曝《巫师4》开发团队扩至250人
青海开学第一课观后感写作辅导(附直播入口)
你是电你是光你是唯一的神话这首歌叫什么名字 你是电你是光你是唯一的神话
国泰君安:地产政策优化 影响几何?
7月PCE数据或小幅回升,美联储内部分歧何时休?
开学季来了!这些路段注意避开!
柳州确诊新冠肺炎的孕妇还能母乳喂养吗
基于股价处于低位 万科决定终止A股定增事项
津门虎无缘足协杯四强 “浪费机会必遭惩罚”果然是足球场上的真理
美军仓皇撤离阿富汗两周年丨美国撤军留下烂摊子 伤痛仍未远离阿富汗
拉萨会是西部的下一个时尚中心吗?
受台风影响,潮州全市中小学校、中职学校、幼儿园开学时间调整为 9月4日
增值税发票怎么开步骤ukey(增值税发票怎么开步骤)
大冒险游戏问题大全(大冒险游戏问题)
韩国政府联合三星电子、SK海力士等开发半导体先进封装技术
看电视现在是一种比较高级的视听享受
新疆女生收到西安网友免费寄的特产
石头科技发布自清洁机器人P10系列:6000Pa的吸力,扫拖联动智能避障
沙特主权财富基金旗下的的油气钻探公司ADES计划在沙特交易所进行IPO
提高综合保税区高质量发展“含金量”
近两月沪深交易所零受理 A股IPO节奏或已按下“放缓键”
本周Steam周销榜出炉:《博德之门3》依旧第一
X 广告
行业动态
X 广告

Copyright ©  2015-2022 大河植物网版权所有  备案号:京ICP备2022022245号-75   联系邮箱:435 226 40@qq.com