考虑此:
loop {
let data = match something() {
Err(err) => {
warn!("An error: {}; skipped.", err);
continue;
},
Ok(x) => x
};
let data2 = match somethingElse() {
Err(err) => {
warn!("An error: {}; skipped.", err);
continue;
},
Ok(x) => x
};
// and so on
}
如果不需要将ok值分配给data
,则可以使用if let Err(err) = something()
,但是上面代码的快捷方式是避免在此代码上粘贴粘贴Err / Ok分支,我认为典型的情况是?类似if let
的东西也将返回ok值。
虽然我认为E_net4的答案可能是最好的答案,但我为后代添加了一个宏,以防创建一个单独的函数,并且由于某些原因使用?
运算符提早返回是不希望的。
这里是一个简单的skip_fail!
宏,当传递错误时continue
是一个包含循环:
macro_rules! skip_fail {
($res:expr) => {
match $res {
Ok(val) => val,
Err(e) => {
warn!("An error: {}; skipped.", e);
continue;
}
}
};
}
此宏可以用作let ok_value = skip_fail!(do_something());
再次,我相信在单独的函数中使用?
,如果没有失败,则返回Ok(end_result)
可能是最惯用的解决方案,因此,如果可以使用该答案,则应该这样做。
如果经常要对结果“展开或继续”,请考虑将该逻辑封装在单独的函数中。有了它,您就可以利用?
语法从函数中引发错误。然后可以在单个位置编写循环的流程逻辑(尽管此时,您可能不再需要continue
)。
loop {
if let Err(err) = do_event() {
warn!("An error: {}; skipped.", err);
// continue; // you also don't need this
}
}
fn do_event() -> Result<(), YourErrorType> {
let data = do_something()?; //
let x = something_more()?; // error propagation!
Ok(())
}
如果必须将多个Ok
链接在一起,则需要在下一个操作中使用一个Ok
的值,并且不关心链中出现错误的where,请考虑[C0 ]:
and_then
and_then
,loop {
let outcome = something()
.and_then(|a| something_else(a))
.and_then(|a| another_thing(a))
.and_then(|a| {
let b = a + salt;
one_more(b)
});
if let Err(e) = outcome {
warn!("An error: {}; skipped.", e);
}
}
,something
和something_else
全部返回某种形式的another_thing
。即使此示例删除了one_more
语句,当Result
的类型为continue
时,and_then
也会通过短路有效地模拟它。该线路上的所有其他呼叫将被跳过。
您可以通过仅要求一个函数调用的语句使用非闭包来使之更加简洁:
Result
((请注意函数上没有括号,这表明它们被用作可调用对象,而不是获取其返回值)
如果您愿意使用不稳定的功能,则可以为此使用try块:
Err
正如shepmaster在评论中提到的那样,可以使用立即评估的闭包(即立即调用的函数表达式,简称IIFE),而无需任何不稳定的特征来完成此操作。这是MutantOctopus在解决方案注释中提出的E_net4解决方案的修改。
loop {
let outcome = something()
.and_then(something_else)
.and_then(another_thing)
.and_then(|a| one_more(a + salt));
if let Err(e) = outcome {
warn!("An error: {}; skipped.", e);
}
}