⚠️
Resultと?演算子 — Rustのエラー処理パターン
try-catchなしでエラーを型で扱う方法
Java/Pythonはtry-catchでエラーを捕捉する。問題はどの関数がどの例外を投げるかシグニチャだけでは分からない点だ。Rustはエラーを型システム内に入れた。
Result<T, E> — Tが成功値、Eがエラー値。関数シグニチャを見ればこの関数が失敗し得るか、どんなエラーかすぐ分かる。
fn read_file(path: &str) -> Result<String, io::Error> {
let content = fs::read_to_string(path)?;
Ok(content)
}
?が核心だ。Errなら即座に返却、Okなら中の値を取り出す。try-catchより簡潔でエラー伝搬経路が明示的。
unwrap()はエラー時パニック(クラッシュ)する。プロトタイピングには便利だがプロダクションでは使ってはいけない。
キーポイント
1
失敗し得る関数はResult<T, E>を返す
2
?演算子でエラーを呼び出し元に自動伝搬
3
matchやmap_errでエラーを変換/処理
4
thiserror/anyhowクレートでカスタムエラー型を定義
メリット
- ✓ 関数シグニチャだけでエラー可能性が分かる
- ✓ ?演算子でエラー伝搬が簡潔
デメリット
- ✗ エラー型変換(Fromトレイト)が最初は面倒
- ✗ unwrap多用の誘惑が大きい
ユースケース
ファイル/ネットワークI/O — 失敗が正常フローの一部
CLIツール — ユーザー入力検証エラーを優雅に表示