如何在 Rust 中使用 if else 方法获取错误?

4
我知道在Rust中处理错误的惯用方法是使用match语句,但我正在寻找其他实现相同功能的方法。
use std::fs;

fn main() {
    if let Ok(f) = fs::read_dir("/dummy"){
        println!("First: {:?}", f);
    }else{
        println!("Error");
    }
    
}

这个可以运行,但是我需要在else语句中打印来自fs::read_dir("/dummy")的原始Result错误。我该怎么做?

3
为什么?虽然你可以使用其他方法实现,但它们会比直接使用 match 更加复杂和冗长。例如,更多的 if let 语句,就像这样 let f = fs::read_dir(..); if let Ok(good) = f {}; if let Err(e) = f {},或者函数式风格,像这样 fs::read_dir(...).and_then(|f| println!(...) ).or_else(|e| println!(...)) - Michael Anderson
3
if let 结构的整个意图就是在你不需要其他分支的细节时比 match 更简单。如果你需要这些细节,你就必须使用 match - Jmb
3个回答

4

一般来说,我认为这样的方法不是一个好主意,但你有几个选择。最明显的两个选择是“多个if let”和“函数式”的方法。我提供了匹配版本以供比较。代码可在playground上获取。

fn multiple_if_lets() {
    let f = std::fs::read_dir("/dummy");
    if let Ok(f) = &f {
        println!("First: {:?}", f);
    }
    if let Err(f) = &f {
        println!("Error: {:?}", f);
    }
}

fn functional_style() {
    std::fs::read_dir("/dummy")
        .map(|f| println!("First: {:?}", f))
        .unwrap_or_else(|f| println!("Error: {:?}", f));
}

fn match_style() {
    match std::fs::read_dir("/dummy") {
        Ok(f) => println!("First: {:?}", f),
        Err(f) => println!("Error: {:?}", f),
    }
}

2

自Rust 1.65.0(2022年11月)起,正如Mara Bos所提到的那样,您可以执行以下操作:

let Ok(f) = fs::read_dir("/dummy") else{ println!("Error"); return };
println!("First: {:?}", f);

let-else statements.

You can now write things like:

let Ok(a) = i32::from_str("123") else { return };

without needing an if or match statement.
This can be useful to avoid deeply nested if statements.


1
我不太确定你为什么不想使用match,因为它就像更好的if let!但是你可能会发现使用外部crate像anyhow很有用。你可以非常容易地将所有错误作为一种类型传播,并在有意义的地方添加上下文。
在你的Cargo.toml中。
[dependencies]
anyhow = "1"

在你的代码中
use std::fs;
use anyhow::Context;

fn main() -> anyhow::Result<()> {
    let dir = fs::read_dir("/dummy").context("failed to read dir")?;

    // another fallible function which can return a `Result` with a 
    // different error type.
    do_something(dir).context("failed to do something")?;

    Ok(())
}

如果 read_dir 在这里失败,您的程序将退出,并输出以下内容。
Error: failed to read dir

Caused by:
    No such file or directory (os error 2)

如果你想要忽略错误但仍然打印出来,你仍然可以使用match
let dir = match fs::read_dir("/dummy").context("failed to read dir") {
    Ok(dir) => Some(dir),
    Err(err) => {
        eprintln!("Error: {:?}", err);
        None
    }
};

这将会输出类似以下的内容,但仍然继续执行:
Error: failed to read dir

Caused by:
    No such file or directory (os error 2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接