简体   繁体   中英

How to get error using if else method in rust?

I know the idiomatic way to handle errors in rust is using match statement but I am looking for other ways to do the same.

use std::fs;

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

This works but I need the original Result error from fs::read_dir("/dummy") to be printed in the else statement. How can I do it?

Generally, I'd consider such an approach a bad idea, but you do have a few options, the most obvious two being "multiple if let s" and a "functional style" approach. I've included the match version for comparison. The code is available on the 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),
    }
}

I'm not quite sure why you don't want to use match because it is like a better if let ! But you might find it useful to use an external crate like anyhow . You can very easily propagate all errors as one type and also add context where it makes sense.

In your Cargo.toml

[dependencies]
anyhow = "1"

In your code

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

If read_dir had to fail here your program would exit and it would output the following

Error: failed to read dir

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

If you wanted to throw away the error but still print it out you could still use match .

let dir = match fs::read_dir("/dummy").context("failed to read dir") {
    Ok(dir) => Some(dir),
    Err(err) => {
        eprintln!("Error: {:?}", err);
        None
    }
};

This would output something like the following but still continue:

Error: failed to read dir

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

Since Rust 1.65.0 (Nov. 2022), as mentioned by Mara Bos , you can do:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM