rust地基蓝图在哪找_Rust错误处理的思考
Rust的错误处理可能已经领先别的语言两层了,但我们甚至还没有看到终点在哪
RustConf 2020其中一场关于错误处理的报告实在是太精彩了,解决了我遇到过的很多问题,或者至少展示了前进的方向。比如,我以前用Python时写过一个subprocess的wrapper,和报告中的output2功能几乎一样,而现在我们有了Error Reporter的概念。顺便一提,应该使用ui test来测试错误输出。
但不得不说,关于错误处理,还有很多难点。这里简单地谈一下我的经验和思考。
Recoverable and unrecoverable Errors
这是一个已经被聊烂了的话题:程序bug触发panic,例如数组越界;正常行为返回Result,例如文件不存在。但实践中这个界限并不是那么清晰,例如从HashMap取值,常常就写为 &map[key],当key不存在于map中时就会panic。这个和文件不存在其实是非常相似的,那么是不是进行类似的处理就解决了呢?最大的问题在于&map[key]这种写法实在是太方便了,写成map.get(key).expect(&format!("{} not exists {}", key))就已经非常讨厌了(这么写无论是否出错都会构造错误消息,但我不知道更好的写法了,并没有一个expect_with方法);而要写成“正确”的形式map.get(key).ok_or(...)?,你需要构造一个Error,修改当前的函数返回Result,再处理一圈调用了此函数的代码,这实在是太考验人性了,而人性从来是经不起考验的。目前看来,我觉得最好的办法是标一个todo,然后视需求来处理这些todo:如果是小玩具,那就永远todo吧;如果是本地小工具,那就panic了若干次后进行修改,具体次数取决于你的耐性;如果是对正确性和响应要求高的正式项目,那就抽时间集中处理。
再明确一下,我认为&map[key]这种就类似于unwrap,除非逻辑上不可能出错出错了就意味着程序bug,在正式代码里是不应该出现的;尽量使用Error而不是panic。
Fehler
当然我们还是有一些办法来缓解这个问题的。其中我觉得正确得很明显的一个是fehler,Ok-Wrapping实在是太香了,把一个函数从返回T改成返回Result<T, E>只需要加一行attribute。
Anonymous sum types
定义error type是另一个痛点。很多时候一个crate只有一个error type,我理解这是人在懒惰和正确之间做的一个妥协。看到相当一部分人觉得snafu是优于thiserror的库,比如最近有这篇文章;我还没有仔细地对比过两者,但至少有一点我觉得snafu很正确:每个moduel都有单独的Error,而不是整个crate只有一个。更极端地说,我认为(几乎)每个函数都应该有一个Error。这样当然非常繁琐,对于想偷懒的人,Anonymous sum types会非常有用 。而anyhow!这种一次性的error type,本质上就是一种只能用于报告的error type,可能大部分用处都会被取代。
Errors intended for an application's user and errors intended to be handled by code
两者的界限同样并不是特别清晰,原来写在main.rs里的函数可能会被放到单独的文件里,然后再被提取为单独的library。极端一点,所有binary crate的main.rs都应该只是对同级的lib.rs的简单调用,所以理论上几乎不存在仅仅展示用的Error。当然实际上的情况往往恰好相反,能够用anyhow!返回字符串而不是直接unwrap就已经很好了。不过我还是同意应该区分纯报告给用户(于是可以偷懒!)的error和需要代码处理的error的,但区分的标准不是这个error产生于library还是application,而是语义上这个error应该如何处理:library也可以产生前一种error,application也可以产生后一种error。
Warning
Warning是一个Rust社区很少讨论的和error很接近的概念。它们可能会互相转化,之前觉得是硬错误的问题,后来觉得可以继续执行只要log输出一下就行了,反之亦然。核心的一点是,warning同样会需要context、source、backtrace这些以帮助人理解发生了什么。我用过w_result这个库,还是挺好用的。
Vec<Error>
Vec<Warning>的概念比较明显,同样的也有Vec<Error>的问题,调用者有可能需要一次性收集所有错误(尤其是要报告给人的时候)。某种意义上,error可以分为中断性的error和可以继续于是可收集的error,而这两者有时也是根据语义的。而Result<T, Vec<Error>>是和Result<T, Error>不兼容的;或许每个Error Enum都应该有一个List的variant?我知道一个相关的库beau_collector,但它的适用范围并不广。
Async Error
Elm之前版本的教程里提到了用Task优雅地处理异步错误,但具体内容一直是comming soon,然后最新版本整个Error Handling一章都消失了。顺便一提,Rust现在如此优秀的编译错误提示也是来源于elm的。回到Rust,以我极为有限的了解,基本最终还是panic了事。这事可能还没人想明白。
Conclusion
<del>Errors are annoying</del>
整理了一下思路,感觉中断性/可以继续的error/warning可能全都是同一个东西。一个返回T的函数,其实应该返回WResult<T, E, E>,其中E大概是这样的定义:
enum Error {E1,E2,List(Vec<Box<Error>>),
}
函数自身决定返回WOk还是WErr,调用者在收到WErr时只能继续传播或处理,而收到带Warning的WOk时,根据每个具体的Error决定传播(加入自己的Warning或Error列表)还是处理(打log、哪怕是直接丢弃)。近期争取抽空来测试一下这个想法。
rust地基蓝图在哪找_Rust错误处理的思考相关推荐
- rust地基蓝图在哪找_深海迷航蓝图在哪 深海迷航全蓝图及碎片详细坐标位置介绍...
深海迷航蓝图在哪 深海迷航全蓝图及碎片详细坐标位置介绍 2017-12-29 16:49:08来源:游戏下载编辑:云曼衍评论(0) <深海迷航>是一款水下探险类游戏,游戏里面有很多收集元素 ...
- 别让数据坑了你!用置信学习找出错误标注(附开源实现)
星标/置顶小屋,带你解锁 最萌最前沿的NLP.搜索与推荐技术 文 | JayLou娄杰(NLP算法工程师,信息抽取方向) 编 | 北大小才女小轶 美 | Sonata 1 前言 在实际工作中,你是否 ...
- 项目成功的关键是在投资最少的时候找出错误
1 项目成功的关键是在投资最少的时候找出错误. 2 如果在给一个程序找个好名字时感到困难,往往是对这一子程序的功能还不够清楚. 3 编写工作应该从抽象到具体. 4 在确定程序是正确的之前,不要急于编译 ...
- 里rust怎么找蓝图_Rust错误处理
错误处理是程序开发中必不可少的一个环节,在Rust中,错误分成两个类别:可恢复错误和不可恢复错误. 可恢复错误:比如说未找到文件,Rust中用Result<T,E>来实现 不可恢复错误:比 ...
- rust为什么显示不了国服_Rust编程语言初探
静态.强类型而又不带垃圾收集的编程语言领域内,很久没有新加入者参与竞争了,大概大部分开发者认为传统的C/C++的思路已经不太适合新时代的编程需求,即便有Ken Tompson这样的大神参与设计的gol ...
- 如何找出错误ora-07445发生时系统执行的语句
在trace file中查找错误出现时的语句主要分两个步骤:首先找到错误发生时的执行语句,然后需要找到语句中绑定变量的值.Step 1:Find the SQL在跟踪文件中查找字符串"Cur ...
- rust门卡有什么用_Rust能力养成之(10)用Cargo进行项目管理:扩展 调用与优化
前言 上一篇我们讲了Cargo运行测试 Cargo运行实例 Cargo工作空间 当然,Cargo也能够进行扩展,合并外部工具以增强开发体验,在设计上,其可扩展性已经达到非常丰富和恰当的程度.Cargo ...
- rust相框加载图片代码_Rust 能取代 Python,更好的实现神经网络?
Rust 也能实现神经网络? 作者 | Nathan J. Goldbaum译者 | 弯月,责编 | 屠敏出品 | CSDN(ID:CSDNnews)以下为译文:我在前一篇帖子(http://neur ...
- rust火箭基地主楼开启方法_Rust 为什么能成为 Stack Overflow 最受欢迎的语言?
每年,开发者问答网站 Stack Overflow 都会对程序员社区展开年度调查,包括他们最喜爱的技术到工作偏好的所有内容. 在2017 年和2018 年Stack Overflow 年度开发者调查中 ...
最新文章
- 佛山居住证办理(首次)
- 40亿移动设备的用户画像和标签架构实践
- 重磅 !间隔分析正式上线,神策数据分析能力再度增强
- php Function split() is deprecated 的解决办法(转)
- php如何判断提交内容为空,php禁止提交空表单(php空值判断)的方法
- Intellij IDEA关闭 Build窗口提示
- Catalyst 6509交换机配置方案
- 【转】Python可变长度的函数参数
- GIS实战应用案例100篇(十五)-CASS插件应用:如何控制点属性与点名统一
- 构建了我的第一个React Native应用程序之后,我现在确信这是未来。
- 监听是否到达页面滑动的可视区域最底部
- oppo手机计算机,OPPO手机助手
- 重新认识javascript的settimeout和异步
- 清除所有多余的桌面右键菜单
- DOM和Events
- kali linux2019镜像下载,Kali 2019下载_KaLi Linux镜像文件iso下载 2019.1a x86/x64_当载软件站...
- 把pdf转为高清jpg图片,其dpi为300以上
- linux 消息队列实现通信
- 手机QQ邮箱可以发html邮件么,如何使用手机qq邮箱发送邮件
- odd ratio置信区间的计算,你学会了吗?
热门文章
- python中有那几种赋值_详解Python列表赋值复制深拷贝及5种浅拷贝
- php速度慢不怕cpu漏洞,PHP曝远程DOS漏洞可致CPU持续占满,请注意升级_护卫神
- img解包打包工具_Python开发GUI实战:图片转换素描画工具!
- python常用第三方模块多少万_python 常用第三方模块
- 如何调整标题字体大小_软网推荐:找回调整Windows 10字号功能
- oracle java javapath_系统找不到C:\ProgramData\Oracle\Java\javapath\java.exe问题及解决方案...
- 关于ios在H5页面长按识别二维码无效
- vim之添加多行和删除多行
- Hibernate异常之关键字错误
- Map集合HashMap,TreeMap