在 Rust 中,错误分为两类:可恢复错误和不可恢复错误。对于可恢复错误,我们使用 Result 枚举,而对于不可恢复错误,我们使用 panic! 宏。
Rust 中的不可恢复错误:Panic 宏
在 Rust 中,不可恢复错误指的是程序无法安全继续执行的情况。这些错误通过 panic! 宏来处理。当 panic! 被触发时,应用程序将停止执行,并展开栈,这通常会导致进程终止。
示例:索引越界
例如,如果你尝试访问超出向量范围的索引,将会引发 panic:
let names = vec!["Sunny", "Hugo", "Charlie"];
names[10]; // 这将导致 panic
// thread 'main' panicked at src/main.rs:5:10:
// index out of bounds: the len is 3 but the index is 10
在数据无效或无法从错误中恢复的情况下,你可以手动调用 panic! 宏:
panic!("The app cannot continue, please fix data");
// thread 'main' panicked at src/main.rs:2:5:
// The app cannot continue, please fix data
不可恢复错误总结
当程序因关键问题(如数据无效或违反程序假设的情况)而无法继续时,就会发生不可恢复错误。panic! 宏用于在这些错误发生时停止程序执行。
Rust 中的可恢复错误:Result 枚举
与此相对,可恢复错误是指程序可以处理并继续运行的错误。这类错误通过 Result 枚举来处理。
Result 枚举有两个变体:
- Ok(T): 表示成功,包含结果值
- Err(E): 表示失败,包含错误值
enum Result<T, E> {
Ok(T),
Err(E)
}
示例:文件未找到
如果你尝试打开一个不存在的文件,可以在不崩溃程序的情况下处理错误。以下是使用 Result 枚举和 match 语句的示例:
use std::fs::File;
fn main() {
let file = File::open("bad_file.png");
match file {
Ok(f) => {
println!("File found {:?}", f);
},
Err(e) => {
println!("File not found {:?}", e);
}
}
println!("App is still running...");
}
// File not found Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }
// App is still running...
如你所见,程序没有 panic,而是通过打印错误信息来处理错误,应用程序继续运行。
错误处理的辅助方法
你可能见过 Rust 中的 unwrap() 方法,并想知道它的作用。unwrap() 是处理 Result 类型的快捷方式,但存在风险。如果结果是 Ok,unwrap() 返回值。然而,如果结果是 Err,unwrap() 将导致 panic。
你可以用 unwrap() 替换 match 语句:
let file = File::open("bad_file.png").unwrap();
// thread 'main' panicked at src/main.rs:4:43:
// called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }
如你所见,如果文件未找到,程序将 panic 并停止运行。
第二个选项是 expect()。
expect() 方法类似于 unwrap(),但允许你提供自定义错误信息。如果你希望提供更多关于错误的上下文,而不仅仅依赖于默认的 panic 信息,这将非常有用。
let file = File::open("bad_file.png").expect("Ooops something went wrong");
// thread 'main' panicked at src/main.rs:4:43:
// Ooops something went wrong: Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }
结论
- 不可恢复错误:在程序无法继续的情况下使用 panic!。这些错误会停止程序的执行。
- 可恢复错误:使用 Result 枚举来处理程序可以继续的错误。你可以使用 match、unwrap() 或 expect() 来处理这些错误。