使用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
仅用于快速测试和概念验证吗?
我无法确认&#34;我的程序不会在这里崩溃,所以我可以使用unwrap
&#34;如果我真的想在运行时避免panic!
,我认为在生产应用程序中我们想要避免panic!
。
换句话说,如果我使用unwrap
,我可以说我的程序是可靠的吗?或者,即使案件看起来很简单,我也必须避免unwrap
吗?
我看了this回答:
最好在您确定没有错误时使用。
但我不认为自己可以确信&#34;。
我不认为这是一个意见问题,而是一个关于Rust核心和编程的问题。
答案 0 :(得分:23)
虽然整个“错误处理” - 主题非常复杂并且经常以意见为基础,但这个问题实际上可以在这里得到解答,因为Rust有相当狭隘的哲学。那就是:
panic!
编程错误(“错误”)Result<T, E>
和Option<T>
进行适当的错误传播和处理 可以将unwrap()
视为转换这两种错误(它将可恢复的错误转换为panic!()
)。当您在程序中编写unwrap()
时,您会说:
此时,
None
/Err(_)
值是编程错误,程序无法从中恢复。
例如,假设您正在使用HashMap
,并希望插入一个您可能希望稍后变异的值:
age_map.insert("peter", 21);
// ...
if /* some condition */ {
*age_map.get_mut("peter").unwrap() += 1;
}
这里我们使用unwrap()
,因为我们可以确定密钥包含值。如果它没有,甚至更重要,那将是一个编程错误:它不是真正可以恢复的。在那一点上,当你使用密钥"peter"
没有价值时,你会怎么做?再试一次插入......?
但是你可能知道,Rust的标准库中的地图有一个漂亮的entry
API。使用该API,您可以避免所有这些unwrap()
。这适用于几乎所有情况:您经常可以重新构建代码以避免unwrap()
!只有极少数情况下才有办法解决。但是如果你想发出信号就可以使用它了:在这一点上,这将是一个编程错误。
最近有一篇关于“错误处理”主题的相当受欢迎的博客文章,其结论类似于Rust的哲学。它很长但值得一读:“The Error Model”。以下是我总结与此问题相关的文章:
总结:当您确定所获得的可恢复的错误实际上不可恢复时,请使用unwrap()
点。在受影响的线上方的评论中解释“为什么?”的奖励积分;-)
答案 1 :(得分:5)
换句话说,如果我使用unwrap,我可以说我的程序是可靠的吗?或者即使案件看起来很简单,我也必须避免打开包裹吗?
我认为明智地使用unwrap
是你必须学会处理的东西,它是不可避免的。
我的修辞问题是:
(1)就像解包,索引恐慌,如果你犯了合同违规并尝试索引越界。这可能是程序中的一个错误,但它并没有像调用unwrap
一样受到关注。
(2)就像解包,整数除法恐慌。
(3)与unwrap不同,add不会检查发布版本中的溢出,因此它可能会无声地导致环绕和逻辑错误。
当然,有一些策略可以处理所有这些,而不会在代码中留下恐慌的情况,但许多程序只是简单地使用边界检查。
答案 2 :(得分:3)
这里有两个问题:
panic!
的使用unwrap
的使用 panic!
是一个工具,在Rust中用于表示不可恢复的情况/违反的假设。它可以用来崩溃一个在面对这个失败时无法继续运行的程序(例如,OOM情况),或者解决编译器知道它无法执行(目前)。
unwrap
是一种便利,最好在生产中避免使用。关于unwrap
的问题在于它没有说明违反了哪个假设,最好使用功能相同的expect("")
,但也会给出错误的线索(不打开源代码)码)。
答案 3 :(得分:2)
unwrap()
不一定是危险的。与unreachable!()
一样,有些情况下您可以确定某些条件不会被触发。
返回Option
或Result
的函数有时只适用于更广泛的条件,但由于程序结构的原因,这些情况可能永远不会发生。
例如:当您从Vec
创建一个迭代器时,您知道它的确切长度,并且可以确定在其上调用next()
多长时间会返回Some<T>
(你可以安全地unwrap()
它。
答案 4 :(得分:-2)
展开对于原型制作非常有用,但对于生产而言并不安全。完成初始设计后,您可以返回并将import multiprocessing as mp
import numpy as np
def foo(p):
global i
return p*i
global lower, upper
lower = 1
upper = 4
for i in range(lower, upper):
if __name__ == '__main__':
dataset = np.linspace(1, 100, 100)
agents = mp.cpu_count() - 1
chunksize = 5
pool = mp.Pool(processes=agents)
result = pool.map(foo, dataset, chunksize)
print result
print i
pool.close()
pool.join()
替换为unwrap()
。