我们什么时候应该在 Rust 中使用 unwrap 和 expect

man*_*nth 8 rust

我是 Rust 的新手,并试图了解我们什么时候应该使用 unwrap 和 expect。

这是一个示例代码:

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();

    let query = args.get(1).unwrap();
    println!("query from unwrawp: {}", query);

    let query = args.get(1).expect("insufficient arguments");
    println!("query from expect: {}", query);

    //$ cargo run hello
    //OUTPUT:
    //query from expect: hello
    //query from unwrawp: hello

}
Run Code Online (Sandbox Code Playgroud)

我观察到的唯一区别是期望中有一个自定义的恐慌消息。
这两者是否可以互换,或者是否有任何特殊情况我们应该使用一种而不是另一种?

Duf*_*ffJ 19

Alexander Fadeev 的答案是正确的,但Rust Book (Ch 9)中有更多信息:

\n
\n

unwrap当您有一些其他逻辑可以确保 willResult有一个值时,调用它也是合适的Ok,但该逻辑不是编译器理解的\xe2\x80\x99。你\xe2\x80\x99仍然有一个Result需要处理的值:无论你\xe2\x80\x99调用什么操作,一般来说仍然有失败的可能性,即使它\xe2\x80\x99在你的特定情况下逻辑上是不可能的情况。如果您可以通过手动检查代码来确保您\xe2\x80\x99永远不会有Err变体,则\xe2\x80\x99完全可以调用unwrap. 这里\xe2\x80\x99s 是一个例子:

\n
\n
use std::net::IpAddr;\n\nlet home: IpAddr = "127.0.0.1".parse().unwrap();\n
Run Code Online (Sandbox Code Playgroud)\n
\n

我们\xe2\x80\x99IpAddr通过解析硬编码字符串来创建一个实例。我们可以看到这127.0.0.1是一个有效的IP地址,因此可以在这里使用它\xe2\x80\x99 unwrap。然而,拥有一个硬编码的有效字符串并不会改变方法的返回类型parse:我们仍然得到一个Result值,并且编译器仍然会让我们处理该变体Result,就好像Err变体是可能的一样,因为编译器不xe2\x80\x99t 足够聪明,可以看到该字符串始终是有效的 IP 地址。如果 IP 地址字符串来自用户而不是硬编码到程序中,因此确实有失败的可能性,那么我们\xe2\x80\x99d 肯定希望Result以更稳健的方式来处理。

\n
\n

因此,如果您知道错误永远不会发生,但编译器希望您处理错误,unwrap那么如果您使用expect.

\n


Ale*_*eev 14

Rust 没有函数重载,所以应该有一种方法可以声明“unwrap带有消息”,那就是expect.

  1. expect==unwrap有消息
  2. expect_err==unwrap_err有消息

关于“ unwrap vs expectRust Book(Ch 9)的使用场景说:

使用 expect 而不是 unwrap 并提供良好的错误消息可以传达您的意图并使追踪恐慌的来源更容易。因为此错误消息以我们指定的文本开头...更容易在代码中找到此错误消息的来源。

  • FWIW,除了函数重载之外,还可以使用可选参数来实现相同的目的,而 Rust 也没有。 (5认同)