错误是程序中会导致不期望输出的意外行为或事件。
在 Rust 中,错误分为两类:
- 不可恢复错误
- 可恢复错误
Rust 中的不可恢复错误
不可恢复错误是程序会停止执行的错误。顾名思义,我们无法从不可恢复错误中恢复。
这些错误称为 **panic**,可以通过显式调用 `panic!` 宏来触发。
让我们看一个使用 `panic!` 宏的示例。
示例 1:使用 panic! 宏的 Rust 不可恢复错误
fn main() {
println!("Hello, World!");
// Explicitly exit the program with an unrecoverable error
panic!("Crash");
}
输出
Hello, World! thread 'main' panicked at 'Crash', src/main.rs:5:5
在这里,调用 `panic!` 宏会导致不可恢复错误。
thread 'main' panicked at 'Crash', src/main.rs:5:5
请注意,程序仍然会执行 `panic!` 宏之上的表达式。在错误消息显示之前,我们仍然可以看到 `Hello, World!` 打印到屏幕上。
`panic!` 宏将错误消息作为参数。
示例 2:Rust 不可恢复错误
不可恢复错误也会通过执行可能导致代码 panic 的操作来触发。例如,访问数组越界会引起 panic。
fn main() {
let numbers = [1, 2 ,3];
println!("unknown index value = {}", numbers[3]);
}
错误
error: this operation will panic at runtime --> src/main.rs:4:42 | 4 | println!("unknown index value = {}", numbers[3]); | ^^^^^^^^^^ index out of bounds: the length is 3 but the index is 3 |
在这里,Rust 会阻止我们编译程序,因为它知道该操作会在运行时 panic。
数组 `numbers` 在索引 **3** 处没有值,即 `numbers[3]`。
可恢复错误
可恢复错误是不会导致程序停止执行的错误。大多数错误都是可恢复的,我们可以根据错误类型轻松采取相应措施。
例如,如果您尝试打开一个不存在的文件,您可以创建该文件,而不是停止程序执行或通过 panic 退出程序。
让我们看一个例子。
use std::fs::File;
fn main() {
let data_result = File::open("data.txt");
// using match for Result type
let data_file = match data_result {
Ok(file) => file,
Err(error) => panic!("Problem opening the data file: {:?}", error),
};
println!("Data file", data_file);
}
如果 `data.txt` 文件存在,则 **输出** 为:
Data file: File { fd: 3, path: "/playground/data.txt", read: true, write: false }
如果 `data.txt` 文件不存在,则 **输出** 为:
thread 'main' panicked at 'Problem opening the data file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:8:23
Result 枚举
在上面的示例中,`File::open('data.txt')` 的返回类型是 `Result
在 Rust 中,`Result
- `Ok(T)` → 操作成功,值为 `T`
- `Err(E)` → 操作失败,错误为 `E`
这里,`T` 和 `E` 是泛型类型。要了解有关泛型或泛型类型的更多信息,请访问 Rust 泛型。
查看 `Result` 枚举是否有值或错误的最基本方法是使用 `match` 表达式进行模式匹配。
// data_file is a Result<T, E>
match data_result {
Ok(file) => file,
Err(error) => panic!("Problem opening the data file: {:?}", error),
};
当结果为 `Ok` 时,此代码将返回 `file`,当结果为 `Err` 时,它将返回 `panic!`。
要了解有关模式匹配的更多信息,请访问 Rust 模式匹配。
Option 枚举
`Option` 类型或 `Option
- `None` → 表示失败且无值
- `Some(T)` → 一个类型为 `T` 的值
我们来看一个例子:
fn main() {
let text = "Hello, World!";
let character_option = text.chars().nth(15);
// using match for Option type
let character = match character_option {
None => "empty".to_string(),
Some(c) => c.to_string()
};
println!("Character at index 15 is {}", character);
}
输出
Character at index 15 is empty
这里,方法 `text.chars().nth(15)` 返回一个 `Option
在上面的示例中,字符串 `text` 的第 15 个索引不存在。因此,`Option` 类型返回 `None`,与 `"empty"` 字符串匹配。
None => "empty".to_string()
如果我们获取字符串 `text` 的第 11 个索引,`Option` 枚举将返回 `Some(c)`,其中 `c` 是第 11 个索引处的字符。
让我们更新上面的示例,找出字符串中的第 11 个索引。
fn main() {
let text = "Hello, World!";
let character_option = text.chars().nth(11);
// using match for Option type
let character = match character_option {
None => "empty".to_string(),
Some(c) => c.to_string()
};
println!("Character at index 11 is {}", character);
}
输出
Character at index 11 is d
Rust 中 Result 和 Option 枚举的区别
`Option` 枚举可以返回 `None`,这可以表示失败。
但是,有时表达操作失败的原因非常重要。因此,我们有了 `Result` 枚举,它提供了 `Err` 并说明了操作失败的原因。
简而言之:
- `Option` 是关于 `Some` 或 `None`(有值或无值)
- `Result` 是关于 `Ok` 或 `Err`(成功结果或错误结果)