引入 ?

有时我们只想要 unwrap 的简单性,而不希望有 panic 的可能。到目前为止,当我们真正想要的是获取变量时,unwrap 迫使我们不断地增加嵌套。这正是 ? 运算符的目的。

当遇到 Err 时,有两种可行的处理方式:

    1. 使用 panic!(我们已经决定尽可能避免这种方式)
    1. 使用 return(因为 Err 表示无法处理该错误)

? 运算符几乎1等同于在遇到 Err 时执行 return 而非 panicunwrap。让我们看看如何简化之前使用组合器的例子:

use std::num::ParseIntError;

fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
    let first_number = first_number_str.parse::<i32>()?;
    let second_number = second_number_str.parse::<i32>()?;

    Ok(first_number * second_number)
}

fn print(result: Result<i32, ParseIntError>) {
    match result {
        Ok(n)  => println!("n 是 {}", n),
        Err(e) => println!("错误:{}", e),
    }
}

fn main() {
    print(multiply("10", "2"));
    print(multiply("t", "2"));
}

try!

? 运算符出现之前,相同的功能是通过 try! 宏实现的。现在推荐使用 ? 运算符,但在查看旧代码时,你可能仍会遇到 try!。使用 try! 宏,前面例子中的 multiply 函数会是这样的:

// 要使用 Cargo 编译并运行此示例而不出错,请将 `Cargo.toml` 文件中
// `[package]` 部分的 `edition` 字段值更改为 "2015"。

use std::num::ParseIntError;

fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
    let first_number = try!(first_number_str.parse::<i32>());
    let second_number = try!(second_number_str.parse::<i32>());

    Ok(first_number * second_number)
}

fn print(result: Result<i32, ParseIntError>) {
    match result {
        Ok(n)  => println!("n 是 {}", n),
        Err(e) => println!("错误:{}", e),
    }
}

fn main() {
    print(multiply("10", "2"));
    print(multiply("t", "2"));
}
1

更多详情请参阅重新认识 ?