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.