Day 6:Result 與自訂錯誤
學習目標
- 理解 Result 的用途
- 用 match / 方法處理成功或失敗
- 定義帶資訊的自訂錯誤列舉
今日重點
Result 是內建的
enum Result<T, E> {
Ok(T),
Err(E),
}
Result 用於「可能失敗」的運算,Err 攜帶錯誤資訊。
基本用法
fn find_user(id: u32) -> Result<String, String> {
if id == 1 {
Ok(String::from("John"))
} else {
Err(format!("User {} not found", id))
}
}
fn main() {
match find_user(1) {
Ok(name) => println!("Found: {}", name),
Err(msg) => println!("Error: {}", msg),
}
}
自訂錯誤列舉
#[derive(Debug)]
enum AppError {
NotFound(String),
PermissionDenied,
InvalidInput(String),
}
impl std::fmt::Display for AppError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
AppError::NotFound(msg) => write!(f, "Not found: {}", msg),
AppError::PermissionDenied => write!(f, "Permission denied"),
AppError::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
}
}
}
常用方法
unwrap() / expect(msg):直接取 Ok,錯就 panic
unwrap_or(default):Err 給預設值
map_err(f):轉換錯誤型別
?:自動傳播錯誤(第 7 週深入)
練習
#[derive(Debug)]
enum ConfigError { MissingKey(String), BadFormat(String) }
fn load_config(text: &str) -> Result<Vec<(String, String)>, ConfigError> {
let mut out = vec![];
for line in text.lines() {
let Some((k, v)) = line.split_once('=') else {
return Err(ConfigError::BadFormat(line.to_string()));
};
out.push((k.to_string(), v.to_string()));
}
Ok(out)
}
1. 實作以上解析,分別測成功與失敗(格式錯誤)。
2. 用 Result 加上 unwrap_or 提供預設設定。
自我檢查
深入連結
- The Book 第 9 章「Recoverable Errors with Result」