我应该避免在生产应用程序中打开包装吗?

rap*_*2-h 16 error-handling rust

在运行时很容易崩溃unwrap:

fn main() {
    c().unwrap();
}

fn c() -> Option<i64> {
    None
}
Run Code Online (Sandbox Code Playgroud)

结果:

   Compiling playground v0.0.1 (file:///playground)
 Running `target/debug/playground`
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', ../src/libcore/option.rs:325
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: Process didn't exit successfully: `target/debug/playground` (exit code: 101)
Run Code Online (Sandbox Code Playgroud)

unwrap唯一专为快速测试和证明的概念?

我不能肯定"我的程序不会崩溃,所以我可以使用unwrap",如果我真的想panic!在运行时避免,我认为避免panic!是我们想要的生产应用程序.

换句话说,如果我使用,我可以说我的程序是可靠的unwrap吗?或者unwrap即使案件看似简单,我也必须避免吗?

我读到了这个答案:

当您确定没有错误时,最好使用它.

但我认为我不能"肯定".

我不认为这是一个意见问题,而是一个关于Rust核心和编程的问题.

Luk*_*odt 26

而整个"错误处理" -topic非常复杂,基于经常认为,这一问题实际上可以在这里找到答案,因为锈病而窄的理念.那是:

  • panic!对于编程错误("错误")
  • 正确的错误传播和处理与Result<T, E>Option<T>预期和可恢复的错误

人们可以想到的unwrap()转换这两种类型的错误之间(这是将可恢复的错误到panic!()).当你写unwrap()你的程序时,你说:

此时,None/ Err(_)值是编程错误,程序无法从中恢复.


例如,假设您正在使用a HashMap并且想要插入一个您可能希望稍后变异的值:

age_map.insert("peter", 21);
// ...

if /* some condition */ {
    *age_map.get_mut("peter").unwrap() += 1;
}
Run Code Online (Sandbox Code Playgroud)

在这里我们使用unwrap(),因为我们可以确定该键具有值.如果它没有,甚至更重要,那将是一个编程错误:它不是真正可以恢复的.当你在那一点上没有钥匙的价值时你会怎么做"peter"?再试一次插入......?

但是您可能知道,Rust的标准库中有一个漂亮的地图entryAPI.使用该API,您可以避免所有这些unwrap().这适用于几乎所有情况:您可以经常重构您的代码以避免unwrap()!只有极少数情况下才有办法解决.但是如果你想发出信号就可以使用它:在这一点上,这将是一个编程错误.


最近有一篇关于"错误处理"主题的相当受欢迎的博客文章,其结论类似于Rust的哲学.它相当长但值得一读:"错误模型".这是我尝试总结与此问题相关的文章:

  • 故意区分编程错误可恢复的错误
  • 使用"快速失败"方法编写错误

总结:unwrap()当您确定所获得的可恢复错误实际上在此时无法恢复时使用.在受影响的线上方的评论中解释"为什么?"的奖励积分;-)

  • 我宁愿他使用 `expect("")` 来说明他在字符串中的期望,而不是用 `unwrap()` 来说明上面评论中的期望! (2认同)

blu*_*uss 5

换句话说,如果我使用unwrap,我可以说我的程序是可靠的吗?或者即使案件看起来很简单,我也必须避免打开包裹吗?

我认为unwrap明智地使用是你必须学会​​处理的东西,它不能只是避免.

我的修辞问题是:

  1. 如果我在向量,数组或切片上使用索引,我可以说我的程序是可靠的吗?
  2. 如果我使用整数除法,我可以说我的程序是可靠的吗?
  3. 如果我添加数字,我可以说我的程序是可靠的吗?

(1)就像解包,索引恐慌,如果你违反合同并尝试索引越界.这将是程序中的一个错误,但它没有像调用那样引起注意unwrap.

(2)如果除数为零,就像解包,整数除法恐慌.

(3)与unwrap不同,添加不检查发布版本中的溢出,因此它可能会静默导致环绕和逻辑错误.

当然,有一些策略可以处理所有这些,而不会在代码中留下恐慌的情况,但是许多程序只是简单地使用例如边界检查.


Mat*_* M. 5

这里有两个问题合二为一:

  • panic!生产中的使用是否可接受
  • unwrap生产中的使用是否可接受

panic!是 Rust 中用来表示无法恢复的情况/违反假设的工具。它可用于使程序崩溃,而该程序在遇到此故障时可能无法继续运行(例如 OOM 情况),也可用于解决编译器知道它无法执行(目前)的问题。

unwrap这是一种便利,在生产中最好避免这种情况。问题unwrap是它没有说明违反了哪个假设,最好使用expect("")功能相同的假设,但也会给出出错的线索(无需打开源代码)。