Error handling 我应该避免在生产应用程序中打开包装吗?
使用Error handling 我应该避免在生产应用程序中打开包装吗?,error-handling,rust,Error Handling,Rust,使用展开,很容易在运行时崩溃: fn main() { c().unwrap(); } fn c() -> Option<i64> { None } unwrap是否仅为快速测试和概念验证而设计 我不能肯定“我的程序不会在这里崩溃,所以我可以使用展开”,如果我真的想避免恐慌在运行时,我想避免恐慌是我们在生产应用程序中需要的 换句话说,如果我使用unwrap,我能说我的程序是可靠的吗?或者,即使情况看起来很简单,我也必须避免unwrap 我读了答案: 当你确信
展开
,很容易在运行时崩溃:
fn main() {
c().unwrap();
}
fn c() -> Option<i64> {
None
}
unwrap
是否仅为快速测试和概念验证而设计
我不能肯定“我的程序不会在这里崩溃,所以我可以使用展开
”,如果我真的想避免恐慌代码>在运行时,我想避免恐慌代码>是我们在生产应用程序中需要的
换句话说,如果我使用unwrap
,我能说我的程序是可靠的吗?或者,即使情况看起来很简单,我也必须避免unwrap
我读了答案:
当你确信自己没有错误时,最好使用它
但我认为我不能“肯定”
我认为这不是一个意见问题,而是一个关于铁锈内核和编程的问题。代码>展开()
不一定是危险的。就像无法访问一样!()
在某些情况下,您可以确保不会触发某些条件
返回选项
或结果
的函数有时仅适用于更广泛的条件,但由于程序的结构,这些情况可能永远不会发生
例如:当您从自己构建的Vec
创建迭代器时,您知道迭代器的确切长度,并且可以确定在其上调用next()
多长时间会返回一个部分(并且您可以安全地unwrap()
它)。虽然整个“错误处理”主题非常复杂,而且通常基于观点,这个问题实际上可以在这里得到回答,因为生锈的哲学范围相当狭窄。即:
- 惊慌失措编程错误的代码>(“错误”)
- 使用
结果
和选项
对预期错误和可恢复错误进行正确的错误传播和处理
可以将unwrap()
看作是在这两种错误之间进行转换(它将可恢复的错误转换为panic!()
)。当您在程序中写入unwrap()
时,您的意思是:
此时,None
/Err()
值是编程错误,程序无法从中恢复
例如,假设您正在使用一个HashMap
,并希望插入一个以后可能需要修改的值:
age_map.insert("peter", 21);
// ...
if /* some condition */ {
*age_map.get_mut("peter").unwrap() += 1;
}
这里我们使用unwrap()。如果不这样做,这将是一个编程错误,更重要的是:它实际上是不可恢复的。如果此时键“peter”
没有值,您会怎么做?尝试再次插入它
但正如你所知,Rust的标准库中有一个很好的地图库。使用该API,您可以避免所有这些unwrap()
s。这几乎适用于所有情况:您经常可以重新构造代码,以避免展开()!只有在极少数情况下,这是无法避免的。但是,如果您想发出信号,那么可以使用它:在这一点上,它将是一个编程错误
最近有一篇关于“错误处理”的颇受欢迎的博客文章,其结论与Rust的哲学相似。这本书很长,但值得一读。以下是我对这篇关于这个问题的文章的总结:
- 故意区分编程错误和可恢复错误
- 对编程错误使用“快速失败”方法
总而言之:当您确定得到的可恢复错误在该点实际上是不可恢复的时,请使用unwrap()
。在受影响行上方的评论中解释“为什么?”的奖励分数;-)
换句话说,如果我使用“展开”,我能说我的程序是可靠的吗?或者即使案件看起来很简单,我也必须避免打开包裹
我认为明智地使用unwrap
是你必须学会处理的事情,这是无法避免的
我反复提出的反问是:
如果我在向量、数组或切片上使用索引,我能说我的程序是可靠的吗
如果我使用整数除法,我能说我的程序是可靠的吗
如果我加上数字,我能说我的程序是可靠的吗
(1) 就像展开,索引恐慌,如果你违反合同并试图索引出界。这可能是程序中的一个bug,但它没有调用unwrap
引起那么多的注意
(2) 与展开类似,如果除数为零,整数除法将陷入恐慌
(3) 与展开不同,添加不会检查发布版本中的溢出,因此它可能会默默地导致概括错误和逻辑错误
当然,有一些策略可以处理所有这些问题,而不会在代码中留下惊慌失措的情况,但许多程序只是简单地使用边界检查作为示例。这里有两个问题合在一起:
- 使用的是
恐慌代码>生产中可接受
- 生产中是否可以使用
展开
惊慌失措代码>是一种工具,用于在Rust中表示无法恢复的情况/违反的假设。它可以用来使一个在这种失败(例如,OOM情况)下无法继续运行的程序崩溃,或者在编译器知道它无法执行时(此时)绕过它
展开
是一种方便,最好在生产中避免。unwrap
的问题在于,它没有说明违反了哪个假设,最好使用功能等效的expect(“”
,但也会给出错误的线索(不打开源代码)。unwrap对于原型制作非常有用,但对于生产来说并不安全。完成初始设计后,返回并用result()替换unwrap()