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
ormatch
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.