理解 Rust 中的不可恢復(fù)錯誤和可恢復(fù)錯誤
在 Rust 中,錯誤分為兩類:可恢復(fù)錯誤和不可恢復(fù)錯誤。對于可恢復(fù)錯誤,我們使用 Result 枚舉,而對于不可恢復(fù)錯誤,我們使用 panic! 宏。
Rust 中的不可恢復(fù)錯誤:Panic 宏
在 Rust 中,不可恢復(fù)錯誤指的是程序無法安全繼續(xù)執(zhí)行的情況。這些錯誤通過 panic! 宏來處理。當(dāng) panic! 被觸發(fā)時,應(yīng)用程序?qū)⑼V箞?zhí)行,并展開棧,這通常會導(dǎo)致進(jìn)程終止。
示例:索引越界
例如,如果你嘗試訪問超出向量范圍的索引,將會引發(fā) panic:
let names = vec!["Sunny", "Hugo", "Charlie"];
names[10]; // 這將導(dǎo)致 panic
// thread 'main' panicked at src/main.rs:5:10:
// index out of bounds: the len is 3 but the index is 10
在數(shù)據(jù)無效或無法從錯誤中恢復(fù)的情況下,你可以手動調(diào)用 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
不可恢復(fù)錯誤總結(jié)
當(dāng)程序因關(guān)鍵問題(如數(shù)據(jù)無效或違反程序假設(shè)的情況)而無法繼續(xù)時,就會發(fā)生不可恢復(fù)錯誤。panic! 宏用于在這些錯誤發(fā)生時停止程序執(zhí)行。
Rust 中的可恢復(fù)錯誤:Result 枚舉
與此相對,可恢復(fù)錯誤是指程序可以處理并繼續(xù)運行的錯誤。這類錯誤通過 Result 枚舉來處理。
Result 枚舉有兩個變體:
- Ok(T): 表示成功,包含結(jié)果值
- 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,而是通過打印錯誤信息來處理錯誤,應(yīng)用程序繼續(xù)運行。
錯誤處理的輔助方法
你可能見過 Rust 中的 unwrap() 方法,并想知道它的作用。unwrap() 是處理 Result 類型的快捷方式,但存在風(fēng)險。如果結(jié)果是 Ok,unwrap() 返回值。然而,如果結(jié)果是 Err,unwrap() 將導(dǎo)致 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." }
如你所見,如果文件未找到,程序?qū)?panic 并停止運行。
第二個選項是 expect()。
expect() 方法類似于 unwrap(),但允許你提供自定義錯誤信息。如果你希望提供更多關(guān)于錯誤的上下文,而不僅僅依賴于默認(rèn)的 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." }
結(jié)論
- 不可恢復(fù)錯誤:在程序無法繼續(xù)的情況下使用 panic!。這些錯誤會停止程序的執(zhí)行。
- 可恢復(fù)錯誤:使用 Result 枚舉來處理程序可以繼續(xù)的錯誤。你可以使用 match、unwrap() 或 expect() 來處理這些錯誤。