Rust - Gestion des erreurs

Dans Rust, les erreurs peuvent être classées en deux grandes catégories, comme indiqué dans le tableau ci-dessous.

Sr. Non Nom et description Usage
1

Recoverable

Erreurs qui peuvent être traitées

Énumération des résultats
2

UnRecoverable

Erreurs qui ne peuvent pas être traitées

macro de panique

Une erreur récupérable est une erreur qui peut être corrigée. Un programme peut réessayer l'opération qui a échoué ou spécifier un autre plan d'action lorsqu'il rencontre une erreur récupérable. Les erreurs récupérables n'entraînent pas l'échec brutal d'un programme. Un exemple d'erreur récupérable est l'erreur File Not Found .

Des erreurs irrécupérables provoquent l'échec brutal d'un programme. Un programme ne peut pas revenir à son état normal si une erreur irrémédiable se produit. Il ne peut pas réessayer l'opération qui a échoué ou annuler l'erreur. Un exemple d'erreur irrémédiable est de tenter d'accéder à un emplacement au-delà de la fin d'un tableau.

Contrairement à d'autres langages de programmation, Rust n'a pas d'exceptions. Il renvoie une énumération Result <T, E> pour les erreurs récupérables, alors qu'il appelle lepanicmacro si le programme rencontre une erreur irrémédiable. La macro panique provoque la fermeture brutale du programme.

Macro de panique et erreurs irrécupérables

panique! macro permet à un programme de se terminer immédiatement et de fournir une rétroaction à l'appelant du programme. Il doit être utilisé lorsqu'un programme atteint un état irrécupérable.

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

Dans l'exemple ci-dessus, le programme se terminera immédiatement lorsqu'il rencontrera la panique! macro.

Production

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

Illustration: panique! macro

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

La sortie est comme indiqué ci-dessous -

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 programme peut provoquer la panique! macro si les règles métier sont violées comme indiqué dans l'exemple ci-dessous -

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'exemple ci-dessus renvoie une erreur si la valeur affectée à la variable est impaire.

Production

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

Énumération des résultats et erreurs récupérables

Résultat Enum - <T, E> peut être utilisé pour gérer les erreurs récupérables. Il a deux variantes -OK et Err. T et E sont des paramètres de type générique. T représente le type de la valeur qui sera renvoyée en cas de succès dans la variante OK, et E représente le type d'erreur qui sera retourné en cas d'échec dans la variante Err.

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

Comprenons cela à l'aide d'un exemple -

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

Le programme renvoie OK (Fichier) si le fichier existe déjà et Err (Erreur) si le fichier n'est pas trouvé.

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

Voyons maintenant comment gérer la variante Err.

L'exemple suivant gère une erreur renvoyée lors de l'ouverture du fichier à l'aide de match déclaration

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- Le programme imprime la fin de l' événement principal même si le fichier n'a pas été trouvé. Cela signifie que le programme a géré correctement l'erreur.

Production

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

Illustration

La fonction is_even renvoie une erreur si le nombre n'est pas un nombre pair. La fonction main () gère cette erreur.

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- Comme la fonction main gère correctement l'erreur, la fin de l' instruction principale est imprimée.

Production

Error msg is NOT_AN_EVEN
end of main

dérouler () et attendre ()

La bibliothèque standard contient quelques méthodes d'assistance que les deux énumérations - Result <T, E> et Option <T> implémentent. Vous pouvez les utiliser pour simplifier les cas d'erreur où vous ne vous attendez vraiment pas à ce que les choses échouent. En cas de succès d'une méthode, la fonction "dérouler" est utilisée pour extraire le résultat réel.

Sr. Non Méthode Signature et description
1 déballer

unwrap(self): T

S'attend à ce que le soi soit Ok / Some et renvoie la valeur contenue à l'intérieur. Si c'estErr ou None au lieu de cela, il soulève une panique avec le contenu de l'erreur affiché.

2 attendre

expect(self, msg: &str): T

Se comporte comme un dépliage, sauf qu'il génère un message personnalisé avant de paniquer en plus du contenu de l'erreur.

déballer()

La fonction unwrap () renvoie le résultat réel qu'une opération réussit. Il renvoie une panique avec un message d'erreur par défaut si une opération échoue. Cette fonction est un raccourci pour l'instruction match. Ceci est illustré dans l'exemple ci-dessous -

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

Modifiez le code ci-dessus pour passer un nombre impair au is_even() fonction.

La fonction unwrap () paniquera et retournera un message d'erreur par défaut comme indiqué ci-dessous

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

attendre()

Le programme peut renvoyer un message d'erreur personnalisé en cas de panique. Ceci est illustré dans l'exemple suivant -

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 fonction expect () est similaire à unwrap (). La seule différence est qu'un message d'erreur personnalisé peut être affiché à l'aide de expect.

Production

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.