使用match(如中的bar)似乎是一种常见方法。
#[derive(Debug)]
pub enum MyErrors {
SomeError,
}
fn foo(x: Option<u64>) -> Result<u64, MyErrors> {
if x.is_none() {
return Err(MyErrors::SomeError);
}
// .. some long code where more options
// are checked and matched
// The ok here is just so the code is simple and compiles
Ok(x.unwrap() * 2)
}
fn bar(x: Option<u64>) -> Result<u64, MyErrors> {
match x {
None => {
return Err(MyErrors::SomeError)?;
}
Some(v) => {
// .. some long code where more options
// are checked and matched
// The ok here is just so the code is simple and compiles
Ok(x.unwrap() * 2)
}
}
}
fn main() {
foo(Some(1));
bar(Some(2));
}
Run Code Online (Sandbox Code Playgroud)
但是,提早返回(例如in foo)会大大减少代码嵌套的样子。如果多次必须解开选项或返回错误,则类似bar这样的代码会非常嵌套...
在空选项情况下尽早返回错误的建议做法是什么?
如果由于内部复杂的逻辑而不希望使用更长的方法链,那么仍然有一些可读性低的选项。
ok_or 和 ?我们可以将Optiona 转换为Result具有所需错误的a,然后立即将其与?运算符解开。此解决方案可能提供最小的缩进,并且可以轻松地用于“解包”多个Options。
fn bar1(x: Option<u64>) -> Result<u64, MyErrors> {
let x = x.ok_or(MyErrors::SomeError)?;
// A lot of stuff going on.
Ok(x * 2)
}
Run Code Online (Sandbox Code Playgroud)
这将评估内部错误,ok_or而不管是否实际使用它。如果此计算昂贵,ok_or_else则延迟产生错误的方法将更加有效(相关问题)。
if let如果嵌套,此解决方案仍会导致代码阶梯化,但是如果else分支逻辑涉及更多,则可能更合适。
fn bar2(x: Option<u64>) -> Result<u64, MyErrors> {
if let Some(x) = x {
// Lot of stuff here as well.
Ok(x * 2)
} else {
Err(MyErrors::SomeError)
}
}
Run Code Online (Sandbox Code Playgroud)
从 Rust 1.65 开始,您可以使用let-else 语句:
fn bar3(x: Option<u64>) -> Result<u64, MyErrors> {
let Some(x) = x else {
return Err(MyErrors::SomeError);
};
Ok(x * 2)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
160 次 |
| 最近记录: |