Day 2:自訂錯誤與 From 轉換

學習目標

  • 定義你自己的錯誤型別
  • 用 From trait 自動轉換底層錯誤
  • 建立多層錯誤的統一入口

今日重點

自訂錯誤型別

use std::io;

#[derive(Debug)]
enum AppError {
    Io(io::Error),
    Parse(String),
    NotFound(String),
}

實作 From 自動轉換

impl From<io::Error> for AppError {
    fn from(error: io::Error) -> Self {
        AppError::Io(error)
    }
}

有了 From<io::Error>,原本回傳 io::Error 的函式用 ? 時,會被自動 .into()AppError

Display(友善錯誤訊息)

impl std::fmt::Display for AppError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            AppError::Io(e) => write!(f, "IO error: {}", e),
            AppError::Parse(msg) => write!(f, "Parse error: {}", msg),
            AppError::NotFound(msg) => write!(f, "Not found: {}", msg),
        }
    }
}
impl std::error::Error for AppError {}   // 讓它成為標準錯誤

使用統一錯誤

fn read_file(path: &str) -> Result<String, io::Error> {
    std::fs::read_to_string(path)
}

fn parse_config(path: &str) -> Result<String, AppError> {
    let contents = read_file(path)?;   // io::Error 自動轉 AppError::Io
    if contents.is_empty() {
        return Err(AppError::Parse("Config is empty".to_string()));
    }
    Ok(contents)
}

練習

  1. 定義 AppError,加入一個 Network(String) 變體。
  2. 實作 From<std::net::AddrParseError>
  3. 寫一個函式同時 ? 傳 io 錯和 parse 錯到 AppError。

自我檢查

  • 能定義自己的多變體錯誤
  • 會用 From 讓 ? 自動轉型
  • 能實作 Display 與 std::error::Error
  • 理解「用統一的錯誤型別包裹多種錯誤」的模式

深入連結

  • The Book 第 9 章「Defining a Type of Error / To panic? or not」