Day 3:錯誤處理模式與設計
學習目標
- 總結常用錯誤處理模式
- 建立「錯誤為值」與「錯誤鏈」的思維
- 應用 anyhow/thiserror 到實際結構
今日重點
模式一:錯誤恢復(recovery)
fn process_with_recovery(input: &str) -> Result<i32, String> {
let number: i32 = input.trim().parse()
.map_err(|e| format!("Parse error: {}", e))?;
if number < 0 {
return Err("Number must be positive".to_string());
}
Ok(number * 2)
}
模式二:錯誤鏈(error chain)——多用 ? 串接
fn chain_errors() -> Result<(), anyhow::Error> {
let config = read_config()?; // anyhow 版
let data = load_data(&config)?;
let result = process(data)?;
save(result)?;
Ok(())
}
用 anyhow 讓每一步的錯誤都往上傳,並保留原始來源。
模式三:錯誤作為值(error as value)
enum OperationResult {
Success(String),
Retry(String),
Fail(String),
}
fn execute_operation() -> OperationResult {
match do_something() {
Ok(_) => OperationResult::Success("Done".to_string()),
Err(e) => {
if should_retry(&e) {
OperationResult::Retry(e.to_string())
} else {
OperationResult::Fail(e.to_string())
}
}
}
}
練習
use anyhow::{Result, Context};
struct Db { /* ... */ }
// 1. 寫一個三層函式:connect -> query -> save,全程用 anyhow
fn connect_db(url: &str) -> Result<()> {
if url.is_empty() {
anyhow::bail!("empty url"); // 直接製造錯誤
}
Ok(())
}
// 2. 用 anyhow::bail! 快速回傳錯誤
fn main() -> Result<()> {
connect_db("").context("db setup")?;
Ok(())
}
自我檢查
- 熟練 pattern-rich 錯誤處理
- 知道「錯誤為值」的設計
- 會用 bail! 快速結束
- 能組織多層錯誤
深入連結
- anyhow(bail/Context)+ Rust error handling 社群文章