rust 选项类型和早期返回,当is_none()时返回错误

dfuffjeb  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(127)

使用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));
}

字符串
然而,提前返回(比如在foo中)会大大减少代码的嵌套程度。如果多次需要打开选项或返回错误,那么bar这样的代码就会嵌套得很深。
在空选项的情况下,提前返回错误的推荐做法是什么?

iaqfqrcu

iaqfqrcu1#

如果由于内部逻辑复杂而不希望使用更长的方法链,那么仍然有一些可读的低成本选项。

ok_or?

我们可以将一个Option转换为一个Result,并带有所需的错误,然后立即使用?操作符对其进行解包。这种解决方案可能提供了最少的错误,并且可以很容易地用于“解包”多个Option

fn bar1(x: Option<u64>) -> Result<u64, MyErrors> {
    let x = x.ok_or(MyErrors::SomeError)?;
    // A lot of stuff going on.
    Ok(x * 2)
}

字符串
这将评估ok_or内部的错误,而不管它是否会被实际使用。如果这个计算是昂贵的,那么ok_or_else,它会产生延迟的错误,将更有效(related question)。

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)
    }
}

dtcbnfnu

dtcbnfnu2#

从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)
}

字符串

相关问题