我有一个函数只能返回一个错误,所以我想创建一次,并在需要时返回该实例。
下面是一个示例:
fn foo() -> Result<(), String> {
let err = String::from("error message");
let a = function_that_returns_an_option().ok_or_else(|| err)?;
let b = function_that_returns_another_option().ok_or_else(|| err)?;
// ...do something with a and b...
Ok(())
}
这导致以下编译错误:
error[E0382]: use of moved value: `err`
--> src/main.rs:12:61
|
10 | let err = String::from("error message");
| --- move occurs because `err` has type `String`, which does not implement the `Copy` trait
11 | let a = function_that_returns_an_option().ok_or_else(|| err)?;
| -- --- variable moved due to use in closure
| |
| value moved into closure here
12 | let b = function_that_returns_another_option().ok_or_else(|| err)?;
| ^^ --- use occurs due to use in closure
| |
| value used here after move
我认为移动是懒惰的,但如果我理解正确的话,即使闭包没有执行,err
也会移动到第一个闭包,因此它不能在第二个闭包中使用(或者编译器不知道这一点,为了安全起见拒绝了它?(。我可以用err.clone()
替换闭包中的err
,但这有点违背目的。是否还有另一个";惯用的";怎么做?
要有一个可以"动态检查"方式移出的变量,可以将值包装在Option
中并使用Option::take
:
let mut err = Some(String::from("error message"));
let a = function_that_returns_an_option().ok_or_else(|| err.take().unwrap())?;
let b = function_that_returns_another_option().ok_or_else(|| err.take().unwrap())?;
(需要.unwrap()
,因为.take()
返回Option<String>
,因为该值可能已经被取了。(
然而,无论如何,这并不是错误处理的最佳选项,因为即使函数成功,也要分配错误字符串。有一种简单的方法可以避免这种情况,并进一步简化代码:将分配放入闭包中,并重用闭包而不是消息值:
let err = || String::from("error message");
let a = function_that_returns_an_option().ok_or_else(err)?;
let b = function_that_returns_another_option().ok_or_else(err)?;