Ruggine - Gestione degli errori

In Rust, gli errori possono essere classificati in due categorie principali come mostrato nella tabella seguente.

Suor n Nome e descrizione Utilizzo
1

Recoverable

Errori che possono essere gestiti

Enumerazione dei risultati
2

UnRecoverable

Errori che non possono essere gestiti

macro di panico

Un errore recuperabile è un errore che può essere corretto. Un programma può ritentare l'operazione non riuscita o specificare un'azione alternativa quando rileva un errore recuperabile. Gli errori ripristinabili non provocano il malfunzionamento improvviso di un programma. Un esempio di errore recuperabile è l'errore File non trovato .

Errori irreversibili causano il malfunzionamento di un programma. Un programma non può tornare al suo stato normale se si verifica un errore irreversibile. Non può ritentare l'operazione non riuscita o annullare l'errore. Un esempio di errore irreversibile è il tentativo di accedere a una posizione oltre la fine di un array.

A differenza di altri linguaggi di programmazione, Rust non ha eccezioni. Restituisce un'enumerazione Risultato <T, E> per gli errori recuperabili, mentre chiama il filepanicmacro se il programma rileva un errore irreversibile. La macro panico provoca la chiusura improvvisa del programma.

Macro di panico ed errori irreversibili

panico! consente a un programma di terminare immediatamente e fornire un feedback al chiamante del programma. Dovrebbe essere usato quando un programma raggiunge uno stato irrecuperabile.

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

Nell'esempio sopra, il programma terminerà immediatamente quando incontra il panico! macro.

Produzione

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

Illustrazione: panico! macro

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

L'output è come mostrato di seguito:

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.

Un programma può invocare il panico! macro se le regole aziendali vengono violate come mostrato nell'esempio seguente:

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

L'esempio precedente restituisce un errore se il valore assegnato alla variabile è dispari.

Produzione

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

Enumerazione dei risultati ed errori ripristinabili

Enum Result - <T, E> può essere utilizzato per gestire gli errori recuperabili. Ha due varianti:OK e Err. T e E sono parametri di tipo generico. T rappresenta il tipo di valore che verrà restituito in un caso di successo nella variante OK e E rappresenta il tipo di errore che verrà restituito in un caso di errore all'interno della variante Err.

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

Facci capire questo con l'aiuto di un esempio:

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

Il programma restituisce OK (File) se il file esiste già e Err (Errore) se il file non viene trovato.

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

Vediamo ora come gestire la variante Err.

L'esempio seguente gestisce un errore restituito durante l'apertura del file utilizzando l'estensione match dichiarazione

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- Il programma stampa fine della principale manifestazione anche se il file non è stato trovato. Ciò significa che il programma ha gestito correttamente l'errore.

Produzione

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

Illustrazione

La funzione is_even restituisce un errore se il numero non è un numero pari. La funzione main () gestisce questo errore.

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- Dal momento che le principali maniglie funzione di errore con grazia, la fine del principale dichiarazione è stampata.

Produzione

Error msg is NOT_AN_EVEN
end of main

scartare () e aspettare ()

La libreria standard contiene un paio di metodi di supporto che entrambi enumerano: Result <T, E> e Option <T> implementano. Puoi usarli per semplificare i casi di errore in cui davvero non ti aspetti che le cose falliscano. In caso di successo da un metodo, la funzione "scartare" viene utilizzata per estrarre il risultato effettivo.

Suor n Metodo Firma e descrizione
1 scartare

unwrap(self): T

Si aspetta che self sia Ok / Some e restituisce il valore contenuto all'interno. Se èErr o None invece, solleva il panico con il contenuto dell'errore visualizzato.

2 aspettarsi

expect(self, msg: &str): T

Si comporta come scartare, tranne per il fatto che emette un messaggio personalizzato prima di andare nel panico oltre al contenuto dell'errore.

scartare()

La funzione unfrap () restituisce il risultato effettivo di un'operazione riuscita. Restituisce un panico con un messaggio di errore predefinito se un'operazione non riesce. Questa funzione è un'abbreviazione per l'istruzione match. Questo è mostrato nell'esempio seguente:

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

Modificare il codice sopra per passare un numero dispari al file is_even() funzione.

La funzione Unrap () andrà in panico e restituirà un messaggio di errore predefinito come mostrato di seguito

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

aspettarsi()

Il programma può restituire un messaggio di errore personalizzato in caso di panico. Questo è mostrato nel seguente esempio:

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

La funzione wait () è simile a unfrap (). L'unica differenza è che un messaggio di errore personalizzato può essere visualizzato utilizzando Prevedi.

Produzione

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.