Day 7:第七週總結練習
學習目標
- 整合 Result、?、自訂錯誤、panic 決策
- 寫一個會讀檔、解析、處理錯誤的程式
今日重點
本週回顧
- Result
與 ? - 自訂錯誤 + From 轉換
- std::error::Error trait、Box
- Result vs panic 決策
- expect / unwrap、#[should_panic]
綜合練習:設定檔解析器
use std::collections::HashMap;
use std::fs;
#[derive(Debug)]
enum ConfigError {
Io(std::io::Error),
MalformedLine(String),
}
impl From<std::io::Error> for ConfigError {
fn from(e: std::io::Error) -> Self { ConfigError::Io(e) }
}
impl std::fmt::Display for ConfigError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
ConfigError::Io(e) => write!(f, "IO error: {}", e),
ConfigError::MalformedLine(l) => write!(f, "格式錯誤: {}", l),
}
}
}
fn load_config(path: &str) -> Result<HashMap<String, String>, ConfigError> {
let content = fs::read_to_string(path)?; // io 錯自動轉
let mut map = HashMap::new();
for line in content.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue; // 跳過空行與註解
}
let Some((k, v)) = line.split_once('=') else {
return Err(ConfigError::MalformedLine(line.to_string()));
};
map.insert(k.trim().to_string(), v.trim().to_string());
}
Ok(map)
}
fn main() -> Result<(), ConfigError> {
let config = load_config("app.config")?;
for (k, v) in &config {
println!("{} = {}", k, v);
}
Ok(())
}
產生一個
app.config檔案(內容 exdebug=true、port=8080)測試。
挑戰
- 加一個「重複 key 報錯」的行為。
- 思考哪些地方該用 Result、哪些其實該 panic(例如:config 檔案天生就壞 → 傳給呼叫端比較好)。
自我檢查
- 能全文使用 ? + 自訂錯誤
- 會設計「回傳 Result 的 main」
- 能判斷 Result vs panic
- 對錯誤處理有完整把握
週總結
錯誤處理是工程品質的核心。你已能寫出穩健、可讀的錯誤處理程式。
下一週進入並發(執行緒、訊息傳遞、共享狀態)。