结果

ResultOption 类型的一个更丰富的版本,它描述了可能的*错误*而不是可能的*缺失*。

也就是说,Result<T, E> 可能有两个结果之一

  • Ok(T):找到了元素 T
  • Err(E):找到元素 E 时出错

按照惯例,预期结果是 Ok,而意外结果是 Err

Option 类似,Result 有许多与之关联的方法。例如,unwrap() 要么产生元素 T,要么 panic。对于情况处理,ResultOption 之间有许多重叠的组合器。

在使用 Rust 时,您可能会遇到返回 Result 类型的方法,例如 parse() 方法。可能并非总能将字符串解析为其他类型,因此 parse() 返回一个 Result,指示可能出现的失败。

让我们看看成功和不成功地 parse() 一个字符串时会发生什么

fn multiply(first_number_str: &str, second_number_str: &str) -> i32 {
    // Let's try using `unwrap()` to get the number out. Will it bite us?
    let first_number = first_number_str.parse::<i32>().unwrap();
    let second_number = second_number_str.parse::<i32>().unwrap();
    first_number * second_number
}

fn main() {
    let twenty = multiply("10", "2");
    println!("double is {}", twenty);

    let tt = multiply("t", "2");
    println!("double is {}", tt);
}

在不成功的情况下,parse() 会给我们留下一个错误,供 unwrap() 在其上 panic。此外,panic 会退出我们的程序并提供一条令人不快的错误消息。

为了提高错误消息的质量,我们应该更具体地说明返回类型,并考虑显式处理错误。

main 中使用 Result

如果显式指定,Result 类型也可以是 main 函数的返回类型。通常,main 函数的形式如下

fn main() {
    println!("Hello World!");
}

但是,main 也可以具有 Result 的返回类型。如果在 main 函数中发生错误,它将返回一个错误代码并打印错误的调试表示(使用 Debug 特征)。以下示例展示了这种情况,并涉及了下一节中涵盖的方面。

use std::num::ParseIntError;

fn main() -> Result<(), ParseIntError> {
    let number_str = "10";
    let number = match number_str.parse::<i32>() {
        Ok(number)  => number,
        Err(e) => return Err(e),
    };
    println!("{}", number);
    Ok(())
}