如何正确使用Option :: ok_or()方法?

时间:2019-01-04 21:09:19

标签: error-handling rust

我试图了解如何在Rust中使用问号运算符进行错误处理。我有以下代码:

fn main() -> Result<(), &'static str> {
    let foo: i32 = Some("1")
        .ok_or(Err("error 1"))?
        .parse()
        .or(Err("error 2"))?;
    Ok(())
}

由于某些原因,无法编译此代码:

error[E0277]: the trait bound `&str: std::convert::From<std::result::Result<_, &str>>` is not satisfied
 --> src/main.rs:2:20
  |
2 |       let foo: i32 = Some("1")
  |  ____________________^
3 | |         .ok_or(Err("error 1"))?
  | |_______________________________^ the trait `std::convert::From<std::result::Result<_, &str>>` is not implemented for `&str`
  |
  = note: required by `std::convert::From::from`

The Rust book有一个问号运算符的用法示例:

use std::io;
use std::io::Read;
use std::fs::File;

fn read_username_from_file() -> Result<String, io::Error> {
    let mut s = String::new();

    File::open("hello.txt")?.read_to_string(&mut s)?;

    Ok(s)
}

我认为,在处理错误的意义上,它与我的示例没有太大区别。我看不到代码无效的原因。如果应该为所有From实现Result特性,为什么Rust书中的代码可以正常工作?

1 个答案:

答案 0 :(得分:6)

or不同,ok_or占用E,而不是完整的Result<T, E>(因为如果通过Ok则无事可做) 。只需直接传递错误字符串:

fn main() -> Result<(), &'static str> {
   let foo: i32 = Some("1")
       .ok_or("error 1")?
       .parse()
       .or(Err("error 2"))?;
    Ok(())
}

错误消息提及From特征的原因是因为?隐式使用From将表达式的错误类型转换为返回值的错误类型。如果有效,.ok_or(Err("error 1"))将返回值Result<&'static str, Result<_, &'static str>>_几乎可以是任何东西,因为Err未指定)。 ?运算符试图找到将From(表达式的错误类型)转换为Result<_, &'static str>(返回值的错误类型)的&'static str实现。由于不存在这样的From实现,因此编译器会发出错误。