Rust之错误处理(二):带结果信息的可恢复错误

开发环境

  • Windows 10
  • Rust 1.67.1

 

  •  VS Code 1.75.1

   项目工程

这里继续沿用上次工程rust-demo

带结果信息的可恢复错误

大多数错误并没有严重到需要程序完全停止的程度。有时,当一个函数失败时,它的原因是你可以很容易地解释和应对的。例如,如果你试图打开一个文件,但由于该文件不存在而导致操作失败,你可能想创建该文件,而不是终止该进程。

回顾前面章节中的 "用结果处理潜在的失败",结果枚举被定义为有两个变体,OkErr,如下例所示。

enum Result<T, E> {
    Ok(T),
    Err(E),
}

TE是通用类型参数:我们将在后面章节中详细讨论通用类型。你现在需要知道的是,T代表在Ok变量中成功情况下将被返回的值的类型,E代表在Err变量中失败情况下将被返回的错误类型。因为Result有这些通用的类型参数,我们可以在许多不同的情况下使用Result类型和定义在它上面的函数,我们想返回的成功值和错误值可能不同。

让我们调用一个返回结果值的函数,因为这个函数可能会失败。在下例3中,我们尝试打开一个文件。

例3:文件名: src/main.rs

use std::fs::File;

fn main() {
    let greeting_file_result = File::open("hello.txt");  // hello.txt是否存在
    println!("greeting_file_result = {:?}", greeting_file_result )
}

编译运行

cargo run

 File::open 的返回类型是一个 Result<T, E>。通用参数T已经被File::open的实现填入了成功值的类型,即std::fs::File,它是一个文件句柄。错误值中使用的E的类型是std::io::Error。这个返回类型意味着对 File::open 的调用可能会成功,并返回一个我们可以读取或写入的文件句柄。该函数的调用也可能失败:例如,该文件可能不存在,或者我们可能没有访问该文件的权限。File::open函数需要有一种方法来告诉我们它是成功还是失败,同时给我们提供文件柄或错误信息。这些信息正是Result枚举所传达的。

File::open成功的情况下,变量greeting_file_result中的值将是一个Ok的实例,包含一个文件柄。在失败的情况下,greeting_file_result中的值将是一个Err的实例,包含关于发生的错误类型的更多信息。

我们需要在上例2中的代码中添加一些内容,以便根据File::open返回的值采取不同的行动。下例3显示了一种使用基本工具处理结果的方法,即我们在之前章节讨论过的match表达式。

例4:文件名: src/main.rs

use std::fs::File;

fn main() {
    let greeting_file_result = File::open("hello.txt");

    let greeting_file = match greeting_file_result {      // match表达式
        Ok(file) => file,
        Err(error) => panic!("Problem opening the file: {:?}", error),
    };
}

请注意,和Option枚举一样,Result枚举和它的变体已经被前奏带入了范围,所以我们不需要在匹配类中的OkErr变体之前指定Result::

当结果为Ok时,该代码将从Ok变量中返回内部文件值,然后我们将该文件句柄值赋给变量greeting_filematch后,我们可以使用文件句柄来读或写。

match的另一方面处理从File::open获取一个Err值的情况。在这个例子中,我们选择了panic!宏观。如果在我们的当前目录中没有名为hello.txt的文件,并且我们运行了这段代码,我们将会看到下面的输出panic!宏:

编译运行

cargo run

像往常一样,这个输出告诉我们到底哪里出错了。

不同错误的匹配

上例中的代码会panic!不管为什么File::open失败。但是,我们希望针对不同的失败原因采取不同的操作:如果File::open因为文件不存在而失败,我们希望创建该文件并将句柄返回给新文件。如果File::open由于任何其他原因失败—例如,因为我们没有打开文件的权限—我们仍然希望代码panic!就像上例中一样。为此,我们添加了一个内部match表达式,如下例5所示。 

例5:文件名: src/main.rs

use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let greeting_file_result = File::open("hello.txt");

    let greeting_file = match greeting_file_result {
        Ok(file) => file,
        Err(error) => match error.kind() {    // match错误类型
            ErrorKind::NotFound => match File::create("hello.txt") {   // 创建hello,ext
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {:?}", e),
            },
            other_err
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值