问题描述
在运行时很容易崩溃, unwrap
:
It's easy to crash at runtime with unwrap
:
fn main() {
c().unwrap();
}
fn c() -> Option<i64> {
None
}
结果:
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)
unwrap
仅用于快速测试和概念验证?
Is unwrap
only designed for quick tests and proofs-of-concept?
我不能确认我的程序不会在这里崩溃,所以我可以使用 unwrap
如果我真的想避免 panic!
运行时,我想避免 panic!
是我们在生产应用程序中想要的。
I can not affirm "My program will not crash here, so I can use unwrap
" if I really want to avoid panic!
at runtime, and I think avoiding panic!
is what we want in a production application.
换句话说,可以我说我的程序是可靠的,如果我使用 unwrap
?或者我必须避免 unwrap
即使情况看起来很简单?
In other words, can I say my program is reliable if I use unwrap
? Or must I avoid unwrap
even if the case seems simple?
我阅读了答案:
但我不认为我可以肯定地。
But I don't think I can be "positively sure".
我不认为这是一个意见问题,但一个问题关于Rust的核心和编程。
I don't think this is an opinion question, but a question about Rust core and programming.
推荐答案
虽然整个错误处理 - 主题非常复杂,通常是基于意见的,这个问题实际上可以在这里回答,因为Rust有着狭隘的哲学。那就是:
While the whole "error handling"-topic is very complicated and often opinion based, this question can actually be answered here, because Rust has rather narrow philosophy. That is:
-
panic!
编程错误 (bug) - 正确的错误传播和处理与
结果< T,E>
和T>
为预期和可恢复错误
panic!
for programming errors ("bugs")- proper error propagation and handling with
Result<T, E>
andOption<T>
for expected and recoverable errors
可以将这两种错误之间的 unwrap()
转换为转换(将可恢复错误转换为慌!()
)。当您在程序中写入 unwrap()
时,您在说:
One can think of unwrap()
as converting between those two kinds of errors (it is converting a recoverable error into a panic!()
). When you write unwrap()
in your program, you are saying:
例如,说你正在使用一个 HashMap
,并希望插入一个您可能想在以后变异的值:
For example, say you are working with a HashMap
and want to insert a value which you may want to mutate later:
age_map.insert("peter", 21);
// ...
if /* some condition */ {
*age_map.get_mut("peter").unwrap() += 1;
}
这里我们使用 unwrap()
,因为我们可以确定该键保存一个值。如果没有甚至更重要,这将是一个编程错误:它不是真的可以恢复。在这一点上,如果没有键值peter
?尝试再次插入...?
Here we use the unwrap()
, because we can be sure that the key holds a value. It would be a programming error if it didn't and even more important: it's not really recoverable. What would you do when at that point there is no value with the key "peter"
? Try inserting it again ... ?
但是您可能知道,有一个美丽的。使用该API,您可以避免所有这些 unwrap()
s。这种情况适用于几乎所有情况:您可以经常重组代码,以避免 unwrap()
!只有在很少的情况下才有办法。但是,使用它可以,如果你想发信号:在这一点上,这将是一个编程错误。
But as you may know, there is a beautiful entry
API for the maps in Rust's standard library. With that API you can avoid all those unwrap()
s. And this applies to pretty much all situations: you can very often restructure your code to avoid the unwrap()
! Only in a very few situation there is no way around it. But then it's OK to use it, if you want to signal: at this point, it would be a programming bug.
最近有一个颇受欢迎的博客文章是错误处理,其结论与Rust的理念相似。这很长,但值得一看:。这是我的总结与这个问题有关的文章:
There has been a recent, fairly popular blog post on the topic of "error handling" whose conclusion is similar to Rust's philosophy. It's rather long but worth reading: "The Error Model". Here is my try on summarizing the article in relation to this question:
- 刻意区分编程错误和可恢复的错误
- 对编程错误使用fail fast方法
总结:使用 unwrap()
当您确定您获得的可恢复错误实际上是 奖励积分,以解释为什么?在受影响的线上方的评论中;-)
In summary: use unwrap()
when you are sure that the recoverable error that you get is in fact unrecoverable at that point. Bonus points for explaining "why?" in a comment above the affected line ;-)
这篇关于我应该避免在生产应用中展开吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!