Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

エラー処理

mainでエラーを正しく処理する

anyhow-badge cat-rust-patterns-badge thiserror-badge cat-rust-patterns-badge error-chain-badge cat-rust-patterns-badge

エラー戦略 (2024)

Rust by Example で推奨されているように、Boxing errors は使い始めるための 簡単な戦略と見なされています。

use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    // エラーを Box 化する例
    let result: Result<(), Box<dyn Error>> = Ok(());
    result
}

どのような種類のエラー処理が必要になる可能性があるかを理解するには、Designing error types in Rust を読み、ライブラリには thiserror を、保守されている エラー集約の選択肢として anyhow を検討してください。

use thiserror::Error;

#[derive(Error,Debug)]
pub enum MultiError {
  #[error("🦀 got {0}")]
  ErrorClass(String),
}

fn main() -> Result<(), MultiError> {
    // thiserror を使用する例
    Ok(())
}

アプリケーション作成者は anyhow を使って列挙型を構成でき、クレートから Result 型をインポートすることで自動 Box 化の挙動を利用できます

use anyhow::Result;

fn main() -> Result<(), Box<dyn std::error::Error>> {
   let my_string = "yellow".to_string();  
   let _my_int = my_string.parse::<i32>()?;
   Ok(())
}

Error Chain (2015-2018)

存在しないファイルを開こうとしたときに発生するエラーを処理します。これは、 handle errors in Rust ために必要となる多くのボイラープレートコードを担ってくれる ライブラリ error-chain を使うことで実現されます。

foreign_links 内の Io(std::io::Error) により、自動的に std::io::Error から error_chain! で定義された型へ変換でき、 その型は Error トレイトを実装します。

以下のレシピは、Unix ファイル /proc/uptime を開いて内容を解析し、最初の 数値を取得することで、システムがどれだけ長く稼働しているかを示します。 エラーがない限り、稼働時間を返します。

この本の他のレシピでは error-chain のボイラープレートは隠されており、⤢ ボタンで コードを展開すると確認できます。

use error_chain::error_chain;

use std::fs::File;
use std::io::Read;

error_chain!{
    foreign_links {
        Io(std::io::Error);
        ParseInt(::std::num::ParseIntError);
    }
}

fn read_uptime() -> Result<u64> {
    let mut uptime = String::new();
    File::open("/proc/uptime")?.read_to_string(&mut uptime)?;

    Ok(uptime
        .split('.')
        .next()
        .ok_or("Cannot parse uptime data")?
        .parse()?)
}

fn main() {
    match read_uptime() {
        Ok(uptime) => println!("uptime: {} seconds", uptime),
        Err(err) => eprintln!("error: {}", err),
    };
}