What is the Rust equivalent to a try-catch statement?

前端 未结 3 790
情话喂你
情话喂你 2020-12-30 00:19

Is it possible to handle multiple different errors at once instead of individually in Rust without using additional functions? In short: what is the Rust eq

相关标签:
3条回答
  • 2020-12-30 01:04

    There's also an unstable feature called try_blocks (https://doc.rust-lang.org/beta/unstable-book/language-features/try-blocks.html, https://github.com/rust-lang/rust/issues/31436)

    Usage example:

    #![feature(try_blocks)]
    
    fn main() {
        // you need to define the result type explicitly
        let result: Result<(), Error> = try {
            do_step_1()?;
            do_step_2()?;
            do_step_3()?;
        };
    
        if let Err(e) = result {
            println!("Failed to perform necessary steps, ({:?})", e);
        }
    }
    
    fn do_step_1() -> Result<(), Error> { Ok(()) }
    fn do_step_2() -> Result<(), Error> { Ok(()) }
    fn do_step_3() -> Result<(), Error> { Err(Error::SomeError) }
    
    #[derive(Debug)]
    enum Error {
        SomeError,
    }
    
    0 讨论(0)
  • 2020-12-30 01:07

    Results in Rust can be chained using and_then. So you can do this:

    if let Err(e) = do_step_1().and_then(do_step_2).and_then(do_step_3) {
        println!("Failed to perform necessary steps");
    }
    

    or if you want a more compact syntax, you can do it with a macro:

    macro_rules! attempt { // `try` is a reserved keyword
       (@recurse ($a:expr) { } catch ($e:ident) $b:block) => {
          if let Err ($e) = $a $b
       };
       (@recurse ($a:expr) { $e:expr; $($tail:tt)* } $($handler:tt)*) => {
          attempt!{@recurse ($a.and_then (|_| $e)) { $($tail)* } $($handler)*}
       };
       ({ $e:expr; $($tail:tt)* } $($handler:tt)*) => {
          attempt!{@recurse ($e) { $($tail)* } $($handler)* }
       };
    }
    
    attempt!{{
       do_step1();
       do_step2();
       do_step3();
    } catch (e) {
       println!("Failed to perform necessary steps: {}", e);
    }}
    

    playground

    0 讨论(0)
  • 2020-12-30 01:15

    There is no try catch statement in Rust. The closest approach is the ? operator.

    However, you do not have to create a function and a match statement to resolve it in the end. You can define a closure in your scope and use ? operator inside the closure. Then throws are held in the closure return value and you can catch this wherever you want like following:

    fn main() {
        let do_steps = || -> Result<(), MyError> {
            do_step_1()?;
            do_step_2()?;
            do_step_3()?;
            Ok(())
        };
    
        if let Err(_err) = do_steps() {
            println!("Failed to perform necessary steps");
        }
    }
    

    Playground

    Is it possible to handle multiple different errors at once instead of individually in Rust without using additional functions?

    Yes it is possible. There is a failure crate for the error management in Rust. Using Failure, you can chain, convert, concatenate the errors. After converting the error types to one common type, you can catch (handle) it easily.

    0 讨论(0)
提交回复
热议问题