rs.nkmk.me

Rust, anyhowのマクロ(anyhow!, bail!, ensure!)の使い方

Posted: | Tags: Rust, anyhow, エラー処理, マクロ

Rustでanyhowのマクロ(anyhow!, bail!, ensure!)を使うと、関数から簡単にエラーを返すことができる。任意の条件で単発のエラーを返すのに便利。

ここではそれぞれのマクロの使い方について説明する。

anyhowの基本的な使い方については以下の記事を参照。

本記事のサンプルコードにおけるanyhowのバージョンは以下の通り。

anyhow = "1.0"
source: Cargo.toml

use宣言は以下の通り。

use anyhow::{anyhow, bail, ensure, Result};

anyhow!: anyhow::Errorを生成

anyhow!anyhow::Errorを生成する。

引数は文字列で、format!のようにプレースホルダー{}を含められる。もちろん{}なしの文字列でもよい。

fn with_anyhow(i: i32) -> Result<i32> {
    if i < 10 {
        return Err(anyhow!("Value must be at least 10, got {}", i));
    };
    Ok(i)
}

上の例のようにreturnで返す場合、その関数の返り値の型はResult<T, anyhow::Error>とする。use anyhow::Result;としておくと、Result<T>と書ける。

実行結果は以下の通り。

assert_eq!(with_anyhow(10).unwrap(), 10);
assert_eq!(
    with_anyhow(9).unwrap_err().to_string(),
    "Value must be at least 10, got 9"
);

ここでは、簡単のため、返り値に対してunwrapunwrap_errで値やエラーを取り出して確認しているが、実際のプログラムでは適切なエラー処理を行えばよい。以降の例も同じ。

bail!: anyhow::Errorをreturn

bail!anyhow::Errorreturnする。

return Err(anyhow!($args...)と等価。

fn with_bail(i: i32) -> Result<i32> {
    if i < 10 {
        bail!("Value must be at least 10, got {}", i);
    };
    Ok(i)
}

assert_eq!(with_bail(10).unwrap(), 10);
assert_eq!(
    with_bail(9).unwrap_err().to_string(),
    "Value must be at least 10, got 9"
);

anyhow::Errorreturnするので、Result<T, anyhow::Error>を返す関数の中でしか使えない。

ensure!: 条件を満たさないときにanyhow::Errorをreturn

ensure!は第一引数に条件を指定する。その条件を満たさない(falseである)ときにanyhow::Errorreturnする。

if !$cond { return Err(anyhow!($args...)); }と等価。条件に否定の!が付いていることに注意。

fn with_ensure(i: i32) -> Result<i32> {
    ensure!(i >= 10, "Value must be at least 10, got {}", i);
    Ok(i)
}

assert_eq!(with_ensure(10).unwrap(), 10);
assert_eq!(
    with_ensure(9).unwrap_err().to_string(),
    "Value must be at least 10, got 9"
);

条件を満たす場合はスルーし、満たさない場合にエラーを返す。パニックを発生させるのではなくエラーを返すassert!のようなもの。

bail!と同様にanyhow::Errorreturnするので、Result<T, anyhow::Error>を返す関数の中でしか使えない。

関連カテゴリー

関連記事