Rust-error-handling

提供:Dev Guides
移動先:案内検索

Rust-エラー処理

Rustでは、次の表に示すように、エラーを2つの主要なカテゴリに分類できます。

Sr.No Name & Description Usage
1

Recoverable

処理できるエラー

Result enum
2

UnRecoverable

処理できないエラー

panic macro

回復可能なエラーは、修正可能なエラーです。 プログラムは、回復可能なエラーが発生した場合、失敗した操作を再試行するか、代替のアクションコースを指定できます。 回復可能なエラーにより、プログラムが突然失敗することはありません。 回復可能なエラーの例は、_File Not Found_エラーです。

回復不能なエラーが発生すると、プログラムは突然失敗します。 回復不能なエラーが発生した場合、プログラムを通常の状態に戻すことはできません。 失敗した操作を再試行したり、エラーを元に戻すことはできません。 回復不能なエラーの例は、アレイの終わりを超えた場所にアクセスしようとした場合です。

他のプログラミング言語とは異なり、Rustには例外はありません。 回復可能なエラーの場合は列挙型_Result <T、E> _を返しますが、プログラムで回復不能なエラーが発生した場合は panic マクロを呼び出します。 _panic_マクロを使用すると、プログラムが突然終了します。

パニックマクロと回復不能なエラー

_panic!_マクロを使用すると、プログラムをすぐに終了し、プログラムの呼び出し元にフィードバックを提供できます。 プログラムが回復不可能な状態に達したときに使用する必要があります。

fn main() {
   panic!("Hello");
   println!("End of main");//unreachable statement
}

上記の例では、_panic!_マクロに遭遇すると、プログラムはすぐに終了します。

出力

thread 'main' panicked at 'Hello', main.rs:3

イラスト:パニック! マクロ

fn main() {
   let a = [10,20,30];
   a[10];//invokes a panic since index 10 cannot be reached
}

出力は次のようになります-

warning: this expression will panic at run-time
--> main.rs:4:4
  |
4 | a[10];
  | ^^^^^ index out of bounds: the len is 3 but the index is 10

$main
thread 'main' panicked at 'index out of bounds: the len
is 3 but the index is 10', main.rs:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.

プログラムはパニックを引き起こす可能性があります! 下の例に示すようにビジネスルールに違反している場合のマクロ-

fn main() {
   let no = 13;
  //try with odd and even
   if no%2 == 0 {
      println!("Thank you , number is even");
   } else {
      panic!("NOT_AN_EVEN");
   }
   println!("End of main");
}

上記の例は、変数に割り当てられた値が奇数の場合にエラーを返します。

出力

thread 'main' panicked at 'NOT_AN_EVEN', main.rs:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.

結果の列挙と回復可能なエラー

Enum Result – <T、E>は、回復可能なエラーを処理するために使用できます。 OKErr の2つのバリアントがあります。 T および E はジェネリック型パラメーターです。 T はOKバリアント内の成功ケースで返される値のタイプを表し、 E はErrバリアント内の失敗ケースで返されるエラーのタイプを表します。

enum Result<T,E> {
   OK(T),
   Err(E)
}

例の助けを借りてこれを理解しましょう-

use std::fs::File;
fn main() {
   let f = File::open("main.jpg");
  //this file does not exist
   println!("{:?}",f);
}

プログラムは、ファイルが既に存在する場合は_OK(File)_を返し、ファイルが見つからない場合は_Err(Error)_を返します。

Err(Error { repr: Os { code: 2, message: "No such file or directory" } })

Errバリアントの処理方法を見てみましょう。

次の例では、 match ステートメントを使用してファイルを開くときに返されるエラーを処理します

use std::fs::File;
fn main() {
   let f = File::open("main.jpg");  //main.jpg doesn't exist
   match f {
      Ok(f)=> {
         println!("file found {:?}",f);
      },
      Err(e)=> {
         println!("file not found \n{:?}",e);  //handled error
      }
   }
   println!("end of main");
}

注意-ファイルが見つからなかったにもかかわらず、プログラムは_main_イベントの_end_を出力します。 これは、プログラムがエラーを適切に処理したことを意味します。

出力

file not found
Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }
end of main

_is_even_関数は、数値が偶数でない場合にエラーを返します。 main()関数はこのエラーを処理します。

fn main(){
   let result = is_even(13);
   match result {
      Ok(d)=>{
         println!("no is even {}",d);
      },
      Err(msg)=>{
         println!("Error msg is {}",msg);
      }
   }
   println!("end of main");
}
fn is_even(no:i32)->Result<bool,String> {
   if no%2==0 {
      return Ok(true);
   } else {
      return Err("NOT_AN_EVEN".to_string());
   }
}

-main関数はエラーを適切に処理するため、_main_ステートメントの_end_が出力されます。

出力

Error msg is NOT_AN_EVEN
end of main

unwrap()およびexpect()

標準ライブラリには、Result <T、E>とOption <T>の両方を列挙するヘルパーメソッドがいくつか含まれています。 それらを使用して、本当に失敗することを期待しないエラーケースを簡素化できます。 メソッドが成功した場合、「unwrap」関数を使用して実際の結果を抽出します。

Sr.No Method Signature & Description
1 unwrap

unwrap(self): T

自分がOk/Someであると期待し、その中に含まれる値を返します。 代わりに Err または None である場合、表示されるエラーの内容でパニックが発生します。

2 expect

expect(self, msg: &str): T

展開のように動作しますが、エラーの内容に加えてパニックする前にカスタムメッセージを出力します。

unwrap()

unwrap()関数は、操作が成功した実際の結果を返します。 操作が失敗した場合、デフォルトのエラーメッセージでパニックを返します。 この関数は、matchステートメントの省略形です。 これは以下の例に示されています-

fn main(){
   let result = is_even(10).unwrap();
   println!("result is {}",result);
   println!("end of main");
}
fn is_even(no:i32)->Result<bool,String> {
   if no%2==0 {
      return Ok(true);
   } else {
      return Err("NOT_AN_EVEN".to_string());
   }
}
result is true
end of main

上記のコードを変更して、奇数を* is_even()*関数に渡します。

_unwrap()_関数はパニックし、以下に示すようにデフォルトのエラーメッセージを返します。

thread 'main' panicked at 'called `Result::unwrap()` on
an `Err` value: "NOT_AN_EVEN"', libcore\result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace

expect()

プログラムは、パニックの場合にカスタムエラーメッセージを返すことができます。 これは、次の例に示されています-

use std::fs::File;
fn main(){
   let f = File::open("pqr.txt").expect("File not able to open");
  //file does not exist
   println!("end of main");
}

関数expect()はunwrap()に似ています。 唯一の違いは、expectを使用してカスタムエラーメッセージを表示できることです。

出力

thread 'main' panicked at 'File not able to open: Error { repr: Os
{ code: 2, message: "No such file or directory" } }', src/libcore/result.rs:860
note: Run with `RUST_BACKTRACE=1` for a backtrace.