什么是Rust等同于try-catch语句?

问题描述 投票:1回答:2

是否可以一次处理多个不同的错误而不是单独使用Rust而不使用其他功能?简而言之:什么是Rust等同于try-catch语句?

像这样的一个功能(First-class error handling with ? and catch)在2016年被提出,但我不知道它是什么以及这个问题的2019解决方案可能是什么样子。

例如,做这样的事情:

try {
    do_step_1()?;
    do_step_2()?;
    do_step_3()?;
    // etc
} catch {
    alert_user("Failed to perform necessary steps");
}

代替:

match do_steps() {
    Ok(_) => (),
    _ => alert_user("Failed to perform necessary steps")
}

// Additional function:
fn do_steps() -> Result<(), Error>{
    do_step_1()?;
    do_step_2()?;
    do_step_3()?;
    // etc
    Ok(())
}

我的程序有一个函数,它检查注册表中的各种不同位置的不同数据值,并返回一些聚合数据。它需要在循环内部的其他try-catch中使用try-catch中的许多try-cache语句。

error-handling rust try-catch
2个回答
5
投票

Rust中没有try catch语句。最接近的方法是?算子。

但是,您不必创建函数和match语句来最终解决它。您可以在范围中定义闭包,并在闭包内使用?运算符。然后抛出保持在闭包返回值中,您可以在以下任何地方捕获:

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

是否可以一次处理多个不同的错误而不是单独使用Rust而不使用其他功能?

对的,这是可能的。在Rust中有一个用于错误管理的failure箱子。使用Failure,您可以链接,转换,连接错误。将错误类型转换为一种常见类型后,您可以轻松捕获(处理)它。


5
投票

Rust中的Results可以使用and_then链接。所以你可以这样做:

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

或者如果你想要一个更紧凑的语法,你可以使用宏:

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

© www.soinside.com 2019 - 2024. All rights reserved.