理解 Rust 中的不可恢復(fù)錯(cuò)誤和可恢復(fù)錯(cuò)誤
在 Rust 中,錯(cuò)誤分為兩類:可恢復(fù)錯(cuò)誤和不可恢復(fù)錯(cuò)誤。對(duì)于可恢復(fù)錯(cuò)誤,我們使用 Result 枚舉,而對(duì)于不可恢復(fù)錯(cuò)誤,我們使用 panic! 宏。
Rust 中的不可恢復(fù)錯(cuò)誤:Panic 宏
在 Rust 中,不可恢復(fù)錯(cuò)誤指的是程序無(wú)法安全繼續(xù)執(zhí)行的情況。這些錯(cuò)誤通過(guò) panic! 宏來(lái)處理。當(dāng) panic! 被觸發(fā)時(shí),應(yīng)用程序?qū)⑼V箞?zhí)行,并展開棧,這通常會(huì)導(dǎo)致進(jìn)程終止。
示例:索引越界
例如,如果你嘗試訪問(wèn)超出向量范圍的索引,將會(huì)引發(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ù)無(wú)效或無(wú)法從錯(cuò)誤中恢復(fù)的情況下,你可以手動(dòng)調(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ù)錯(cuò)誤總結(jié)
當(dāng)程序因關(guān)鍵問(wèn)題(如數(shù)據(jù)無(wú)效或違反程序假設(shè)的情況)而無(wú)法繼續(xù)時(shí),就會(huì)發(fā)生不可恢復(fù)錯(cuò)誤。panic! 宏用于在這些錯(cuò)誤發(fā)生時(shí)停止程序執(zhí)行。
Rust 中的可恢復(fù)錯(cuò)誤:Result 枚舉
與此相對(duì),可恢復(fù)錯(cuò)誤是指程序可以處理并繼續(xù)運(yùn)行的錯(cuò)誤。這類錯(cuò)誤通過(guò) Result 枚舉來(lái)處理。
Result 枚舉有兩個(gè)變體:
- Ok(T): 表示成功,包含結(jié)果值
- Err(E): 表示失敗,包含錯(cuò)誤值
enum Result<T, E> {
Ok(T),
Err(E)
}
示例:文件未找到
如果你嘗試打開一個(gè)不存在的文件,可以在不崩潰程序的情況下處理錯(cuò)誤。以下是使用 Result 枚舉和 match 語(yǔ)句的示例:
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,而是通過(guò)打印錯(cuò)誤信息來(lái)處理錯(cuò)誤,應(yīng)用程序繼續(xù)運(yùn)行。
錯(cuò)誤處理的輔助方法
你可能見過(guò) Rust 中的 unwrap() 方法,并想知道它的作用。unwrap() 是處理 Result 類型的快捷方式,但存在風(fēng)險(xiǎn)。如果結(jié)果是 Ok,unwrap() 返回值。然而,如果結(jié)果是 Err,unwrap() 將導(dǎo)致 panic。
你可以用 unwrap() 替換 match 語(yǔ)句:
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 并停止運(yùn)行。
第二個(gè)選項(xiàng)是 expect()。
expect() 方法類似于 unwrap(),但允許你提供自定義錯(cuò)誤信息。如果你希望提供更多關(guān)于錯(cuò)誤的上下文,而不僅僅依賴于默認(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ù)錯(cuò)誤:在程序無(wú)法繼續(xù)的情況下使用 panic!。這些錯(cuò)誤會(huì)停止程序的執(zhí)行。
- 可恢復(fù)錯(cuò)誤:使用 Result 枚舉來(lái)處理程序可以繼續(xù)的錯(cuò)誤。你可以使用 match、unwrap() 或 expect() 來(lái)處理這些錯(cuò)誤。