这个问号操作员是关于什么的?

时间:2017-03-21 02:50:32

标签: rust

我正在阅读the documentation for File

//..
let mut file = File::create("foo.txt")?;
//..

这一行中的?是多少?我不记得以前在Rust Book中看过它了。

2 个答案:

答案 0 :(得分:75)

您可能已经注意到,Rust没有例外。它有恐慌,但它们的功能有限(它们不能携带结构化信息),并且不鼓励它们用于错误处理(它们用于不可恢复的错误)。

在Rust中,错误处理使用Result。一个典型的例子是:

fn halves_if_even(i: i32) -> Result<i32, Error> {
    if i % 2 == 0 { Ok(i/2) } else { Err(/* something */) }
}

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = match halves_if_even(i) {
        Ok(i) => i,
        e => return e,
    };

    // use `i`
}

这很棒,因为:

  • 在编写代码时,您不会意外忘记处理错误,
  • 阅读代码时,您可以立即看到可能存在错误。
然而,它并不理想,因为它非常冗长。这就是问号运算符?的用武之地。

以上内容可以改写为:

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = halves_if_even(i)?;

    // use `i`
}

更简洁。

此处?的作用相当于上面的match声明。简而言之:如果没有,它会解包Result,如果没有,返回错误。

这有点神奇,但是错误处理需要一些魔法来减少样板,并且与异常不同的是,可以立即看到哪些函数调用可能会或可能不会错误:那些用?装饰的。

另见:

答案 1 :(得分:2)

它用于可传播错误类型Result 的错误传播。它可以包装结果并为您提供内在价值。

不处理错误情况,而是将其传播到调用者代码,仅处理确定情况。好处是,它消除了很多样板并简化了功能的实现。