引入 ?

有时我们只是想 unwrap 且避免产生 panic。到现在为止,对 unwrap 的错误处理都在强迫 我们一层层地嵌套,然而我们只是想把里面的变量拿出来。? 正是为这种情况准备的。

当找到一个 Err 时,可以采取两种行动:

  1. panic!,不过我们已经决定要尽可能避免 panic 了。
  2. 返回它,因为 Err 就意味着它已经不能被处理了。

? 几乎[^†] 就等于一个会返回 Err 而不是 panicunwrap。我们来看看 怎样简化之前使用组合算子的例子:

  1. use std::num::ParseIntError;
  2. fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
  3. let first_number = first_number_str.parse::<i32>()?;
  4. let second_number = second_number_str.parse::<i32>()?;
  5. Ok(first_number * second_number)
  6. }
  7. fn print(result: Result<i32, ParseIntError>) {
  8. match result {
  9. Ok(n) => println!("n is {}", n),
  10. Err(e) => println!("Error: {}", e),
  11. }
  12. }
  13. fn main() {
  14. print(multiply("10", "2"));
  15. print(multiply("t", "2"));
  16. }

try!

? 出现以前,相同的功能是使用 try! 宏完成的。现在我们推荐使用 ? 运算符,但是 在老代码中仍然会看到 try!。如果使用 try! 的话,上一个例子中的 multiply 函数 看起来会像是这样:

  1. use std::num::ParseIntError;
  2. fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
  3. let first_number = try!(first_number_str.parse::<i32>());
  4. let second_number = try!(second_number_str.parse::<i32>());
  5. Ok(first_number * second_number)
  6. }
  7. fn print(result: Result<i32, ParseIntError>) {
  8. match result {
  9. Ok(n) => println!("n is {}", n),
  10. Err(e) => println!("Error: {}", e),
  11. }
  12. }
  13. fn main() {
  14. print(multiply("10", "2"));
  15. print(multiply("t", "2"));
  16. }

[^†]: 更多细节请看? 的更多用法