Rustのエラー処理
panic!による回復不能なエラー処理、Result<T, E>による回復可能なエラー処理、および?演算子によるエラー伝播を解説します。
Rust基礎シリーズの第10回(最終回)です。Rustでは、エラーを大きく2つのカテゴリに分類します。panic! による「回復不能なエラー」と、Result<T, E> による「回復可能なエラー」です。
panic! による回復不能なエラー#
配列の範囲外アクセスなど、プログラムが継続不可能な致命的状態に遭遇すると、Rustは panic! マクロを実行します。これによりエラーメッセージが出力され、スタックが展開(unwind)されてプロセスが終了します。
fn main() {
// panic!("クラッシュしました");
let v = vec![1, 2, 3];
// v[99]; // 自動的にパニックが発生
}rustプログラム自体で回復できない不正な状態が発生した場合にのみ panic! を使用します。
Result による回復可能なエラー#
ファイルのオープンや数値のパースなど、失敗することが予測される操作では、関数は Result<T, E> を返します。
enum Result<T, E> {
Ok(T),
Err(E),
}rustResult は match を使って検査します。
use std::fs::File;
fn main() {
let greeting_file_result = File::open("hello.txt");
let _greeting_file = match greeting_file_result {
Ok(file) => file,
Err(error) => panic!("ファイルオープン時の問題: {error:?}"),
};
}rustショートカット: unwrap と expect#
Result には、T を抽出するか Err 時にパニックを発生させる便利メソッドが用意されています。
let file = File::open("hello.txt").unwrap();
let file = File::open("hello.txt").expect("hello.txtはこのディレクトリに存在する必要があります");rust本番コードでは、クラッシュログに有用なコンテキスト情報を提供できるため unwrap よりも expect を使用することが推奨されます。
? 演算子によるエラー伝播#
関数を執筆する際、エラーをその場で処理せず呼び出し元に返したい場合が頻繁にあります。? 演算子を使用すると、簡潔にエラーを伝播させることができます。
use std::fs::File;
use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut username = String::new();
File::open("hello.txt")?.read_to_string(&mut username)?;
Ok(username)
}
fn main() -> Result<(), io::Error> {
let username = read_username_from_file()?;
println!("ユーザー名: {username}");
Ok(())
}rust? で評価された操作が Err を返した場合、その Err は即座を包括する関数からリターンされます。
まとめ#
Rustのエラー処理は非常に明確です。回復不能な失敗には panic!、回復可能なエラーには Result<T, E>、そして人間工学的な伝播には ? 演算子を使用します。これで全10回のRust基礎シリーズは完結です!