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()