Result

Rust におけるエラーハンドリングの主要な仕組みは Result 列挙型であり、これは標準ライブラリの型について説明した際に少し見ました。

// 著作権 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0

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

fn main() {
    let file: Result<File, std::io::Error> = File::open("diary.txt");
    match file {
        Ok(mut file) => {
            let mut contents = String::new();
            if let Ok(bytes) = file.read_to_string(&mut contents) {
                println!("親愛なる日記へ: {contents} ({bytes} バイト)");
            } else {
                println!("ファイルの内容を読み取れませんでした");
            }
        }
        Err(err) => {
            println!("日記を開けませんでした: {err}");
        }
    }
}
  • Result には 2 つのバリアントがあります。成功値を含む Ok と、何らかの種類のエラー値を含む Err です。

  • 関数がエラーを生成しうるかどうかは、その関数が Result 値を返すことで、関数の型シグネチャにエンコードされます。

  • Option と同様に、エラー処理を忘れる方法はありません。どちらのバリアントを持っているかを確認するために、まず Result に対してパターンマッチしなければ、成功値にもエラー値にもアクセスできません。unwrap のようなメソッドを使うと、堅牢なエラーハンドリングを行わない手早いコードを書きやすくなりますが、その代わり、適切なエラーハンドリングがどこで省略されているかを、ソースコード上で常に確認できます。

さらに詳しく

Rust のエラーハンドリングを、受講者が他のプログラミング言語で慣れ親しんでいるかもしれないエラーハンドリングの慣習と比較すると、理解の助けになるかもしれません。

例外

  • 多くの言語は例外を使用します。たとえば、C++、Java、Python です。

  • ほとんどの例外を持つ言語では、関数が例外を投げうるかどうかは、その型シグネチャの一部としては見えません。これは一般に、関数を呼び出すときに、その関数が例外を投げる可能性があるかどうかを判断できないことを意味します。

  • 一般に例外はコールスタックを巻き戻し、try ブロックに到達するまで上位へ伝播します。コールスタックの深い場所で発生したエラーが、さらに上位にある無関係な関数に影響を与える可能性があります。

エラー番号

  • 一部の言語では、関数の成功時の戻り値とは別に、エラー番号(またはその他のエラー値)を返します。例としては C や Go があります。

  • 言語によってはエラー値の確認を忘れることがあり、その場合、初期化されていない、あるいはその他の理由で無効な成功値にアクセスしてしまう可能性があります。