Rust - obsługa błędów

W Rust błędy można podzielić na dwie główne kategorie, jak pokazano w poniższej tabeli.

Sr.No Nazwa i opis Stosowanie
1

Recoverable

Błędy, które można obsłużyć

Wyliczenie wyniku
2

UnRecoverable

Błędy, których nie można obsłużyć

panika makro

Naprawialny błąd to błąd, który można naprawić. Program może ponowić operację zakończoną niepowodzeniem lub określić inny sposób postępowania, gdy napotka błąd, który można naprawić. Naprawialne błędy nie powodują nagłej awarii programu. Przykładem możliwego do naprawienia błędu jest błąd Nie znaleziono pliku .

Nieodwracalne błędy powodują nagłe awarie programu. Program nie może powrócić do swojego normalnego stanu, jeśli wystąpi nieodwracalny błąd. Nie może ponowić nieudanej operacji ani cofnąć błędu. Przykładem nieodwracalnego błędu jest próba uzyskania dostępu do lokalizacji poza końcem tablicy.

W przeciwieństwie do innych języków programowania, Rust nie ma wyjątków. Zwraca wynik wyliczenia <T, E> dla naprawialnych błędów, podczas gdy wywołujepanicmakro, jeśli program napotka nieodwracalny błąd. Panika makro powoduje, że program zakończy się nagle.

Panika Makro i nieodwracalne błędy

panika! umożliwia natychmiastowe zakończenie programu i przekazanie informacji zwrotnej osobie wywołującej program. Powinien być używany, gdy program osiągnie stan nieodwracalny.

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

W powyższym przykładzie program zakończy działanie natychmiast po napotkaniu paniki! makro.

Wynik

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

Ilustracja: panika! makro

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

Wyjście jest jak pokazano poniżej -

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.

Program może wywołać panikę! makro, jeśli reguły biznesowe zostaną naruszone, jak pokazano w poniższym przykładzie -

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");
}

Powyższy przykład zwraca błąd, jeśli wartość przypisana do zmiennej jest nieparzysta.

Wynik

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

Wynik wyliczenia i naprawialne błędy

Wynik wyliczenia - <T, E> może służyć do obsługi naprawialnych błędów. Ma dwa warianty -OK i Err. T i E są parametrami typu ogólnego. T reprezentuje typ wartości, która zostanie zwrócona w przypadku powodzenia w wariancie OK, a E reprezentuje typ błędu, który zostanie zwrócony w przypadku niepowodzenia w wariancie Err.

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

Zrozummy to na przykładzie -

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

Program zwraca OK (plik), jeśli plik już istnieje, i Err (błąd), jeśli plik nie został znaleziony.

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

Zobaczmy teraz, jak poradzić sobie z wariantem Err.

Poniższy przykład obsługuje błąd zwrócony podczas otwierania pliku przy użyciu rozszerzenia match komunikat

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");
}

NOTE- Odciski Program zakończy się głównym imprezy chociaż plik nie został znaleziony. Oznacza to, że program z wdziękiem poradził sobie z błędami.

Wynik

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

Ilustracja

Funkcja is_even zwraca błąd, jeśli liczba nie jest liczbą parzystą. Funkcja main () obsługuje ten błąd.

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());
   }
}

NOTE- Ponieważ główne uchwyty funkcja błędu wdzięcznie The end of głównego rachunku zostanie wydrukowany.

Wynik

Error msg is NOT_AN_EVEN
end of main

unrap () i oczekiwać ()

Biblioteka standardowa zawiera kilka metod pomocniczych, które implementują obie wyliczenia - Result <T, E> i Option <T> . Możesz ich użyć do uproszczenia przypadków błędów, w których naprawdę nie spodziewasz się, że coś się nie powiedzie. W przypadku powodzenia metody, funkcja „rozpakuj” jest używana do wyodrębnienia rzeczywistego wyniku.

Sr.No metoda Podpis i opis
1 rozwijać

unwrap(self): T

Oczekuje, że self będzie OK / Some i zwraca wartość zawartą w. Jeśli to jestErr lub None zamiast tego wywołuje panikę z wyświetlaną treścią błędu.

2 oczekiwać

expect(self, msg: &str): T

Zachowuje się jak rozpakowywanie, z tą różnicą, że oprócz zawartości błędu generuje niestandardowy komunikat przed panikowaniem.

rozwijać()

Funkcja unrap () zwraca rzeczywisty wynik pomyślnego zakończenia operacji. Zwraca panikę z domyślnym komunikatem o błędzie, jeśli operacja nie powiedzie się. Ta funkcja jest skrótem dla instrukcji match. Pokazuje to poniższy przykład -

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

Zmodyfikuj powyższy kod, aby przekazać nieparzystą liczbę do pliku is_even() funkcjonować.

Funkcja unrap () wywoła panikę i zwróci domyślny komunikat o błędzie, jak pokazano poniżej

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

oczekiwać()

Program może zwrócić niestandardowy komunikat o błędzie w przypadku paniki. Jest to pokazane w poniższym przykładzie -

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");
}

Funkcja Expect () jest podobna do unrap (). Jedyną różnicą jest to, że niestandardowy komunikat o błędzie może zostać wyświetlony za pomocą funkcji Expect.

Wynik

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.