エラーハンドリング構成 in 2020
元ネタ
メモ
std::error::Error
トレイトが抱える問題
スタックトレースがとれない。
アプリケーションとライブラリとでエラーのあり方が異なる
ライブラリにおけるエラー
- 意味のあるエラーを返す必要がある
- ライブラリ内で発生したエラーはライブラリ用にラッピングされるべきである
- ライブラリで定義されるエラーの変更は注意深くあるべきである
アプリケーションにおけるエラー
- エラーを消費する側である
- ユーザーへのエラー表示を考える
- エラーの解析と検証ができるようにする
エラーハンドリングクレート 2選
作者が同一。
thiserror
エラーを定義することが出来る。
use thiserror::Error; /// WordCountError enumerates all possible errors returned by this library. #[derive(Error, Debug)] pub enum WordCountError { /// Represents an empty source. For example, an empty text file being given /// as input to `count_words()`. #[error("Source contains no data")] EmptySource, /// Represents a failure to read from input. #[error("Read error")] ReadError { source: std::io::Error }, /// Represents all other cases of `std::io::Error`. #[error(transparent)] IOError(#[from] std::io::Error), }
anyhow
エラーを表示することが出来る。
use anyhow::{Context, Result}; fn main() -> Result<()> { for filename in env::args().skip(1).collect::<Vec<String>>() { let mut reader = File::open(&filename).context(format!("unable to open '{}'", filename))?; let wordcount = count_words(&mut reader).context(format!("unable to count words in '{}'", filename))?; println!("{} {}", wordcount, filename); } Ok(()) }
ファイルが存在しなかった場合
$ cargo run --quiet -- words.txt Error: unable to open 'words.txt' Caused by: No such file or directory (os error 2)
readでエラーが発生した場合
$ cargo run --quiet -- words.txt Error: unable to count words in 'words.txt' Caused by: 0: Error encountered while reading from input 1: read: broken pipe
スタックトレースが表示される。
関連
The ? operator for easier error handling - The Edition Guide