Day 1:thiserror——簡化錯誤定義

學習目標

  • 用 thiserror 快速定義錯誤
  • 用屬性標註錯誤訊息
  • 自動取得 Display 與 Error trait

今日重點

安裝

[dependencies]
thiserror = "1"

thiserror 精簡語法

use thiserror::Error;

#[derive(Error, Debug)]
enum DatabaseError {
    #[error("Connection failed: {0}")]
    Connection(String),

    #[error("Query failed: {0}")]
    Query(String),

    #[error("Not found: {0}")]
    NotFound(String),
}

只要一個 #[derive(Error)] 加上 #[error("...")],就自動實作 Displaystd::error::Error。不用再手寫 match。

搭配 From(自動轉換)

#[derive(Error, Debug)]
enum AppError {
    #[error("storage error: {0}")]
    Io(#[from] std::io::Error),   // 自動產生 From

    #[error("bad input: {0}")]
    Invalid(String),
}

fn read(path: &str) -> Result<String, AppError> {
    Ok(std::fs::read_to_string(path)?)   // io::Error 自動轉 AppError::Io
}

在欄位加 #[from],thiserror 自動實作 From,所以 ? 能直接轉換。

練習

use thiserror::Error;

#[derive(Error, Debug)]
enum ConfigError {
    #[error("missing key: {0}")]
    MissingKey(String),
    #[error("parse error: {0}")]
    Parse(#[from] std::num::ParseIntError),
}
1. 定義以上錯誤並用 ? 觸發 Parse 轉換。 2. 對比手寫 Display 與 thiserror 的程式量。

自我檢查

  • 會用 thiserror 定義錯誤
  • 知道 #[error] 屬性
  • 知道 #[from] 自動轉換
  • 比較出手寫與 thiserror 的差異

深入連結

  • thiserror crate 文件(docs.rs/thiserror)