Passer au contenu principal
eLearner.app
Module 7 · Leçon 2 sur 214/14 dans le cours~15 min
Leçons du module (2/2)

Gestion des erreurs et opérateur ?

La philosophie Rust encourage à reconnaître explicitement la possibilité d'erreurs et à structurer le code pour les gérer avant la compilation du programme.

Les erreurs dans Rust sont divisées en deux catégories principales : les erreurs irrécupérables (provoquant un blocage immédiat via la panique panic!) et les erreurs récupérables (gérées via le type Result<T, E>).


Le type Résultat<T, E> et la correspondance de modèle

La plupart des erreurs récupérables renvoient un type Result<T, E> qui est une énumération définie comme :

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

Nous pouvons utiliser la correspondance de modèles pour inspecter le résultat :

Code
use std::fs::File;

fn main() {
    let greeting_file_result = File::open("hello.txt");

    let greeting_file = match greeting_file_result {
        Ok(file) => file,
        Err(error) => panic!("Problema nell'aprire il file: {:?}", error),
    };
}

Propagation d'erreur avec l'opérateur ?

Lorsque nous implémentons une fonction, au lieu de gérer l'erreur directement à l'intérieur de celle-ci, nous souhaitons souvent renvoyer l'erreur à l'appelant afin qu'il puisse décider quoi faire. Ce processus est appelé propagation des erreurs.

Rust fournit l'opérateur ? comme raccourci syntaxique pour la propagation des erreurs. Si la valeur d'un Result est Ok, la valeur contenue dans Ok est renvoyée par l'expression ; s'il s'agit de Err, l'erreur Err est renvoyée par toute la fonction actuelle comme si nous avions utilisé un return Err(...).

Code
use std::fs::File;
use std::io::{self, Read};

fn read_username_from_file() -> Result<String, io::Error> {
    let mut username_file = File::open("username.txt")?;
    let mut username = String::new();
    username_file.read_to_string(&mut username)?;
    Ok(username)
}

[!IMPORTANT] L'opérateur ? ne peut être utilisé que dans les fonctions qui renvoient un type compatible avec la valeur à laquelle il est appliqué (généralement Result, Option ou des types qui implémentent FromResidual).


Erreurs personnalisées

Nous pouvons définir nos propres types d'erreur en implémentant le trait std::fmt::Display (et éventuellement std::error::Error) pour fournir une représentation lisible par l'homme de l'erreur :

Code
use std::fmt;

#[derive(Debug)]
struct MyError {
    details: String,
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Errore: {}", self.details)
    }
}

impl std::error::Error for MyError {}

Essayez-le vous-même

Exercice 1 : Lire un fichier avec le ? opérateur

Exercice#rust.m7.l2.e1
Tentatives : 0Chargement…

Complétez la fonction read_username_from_file pour utiliser le ? opérateur. pour propager les erreurs générées en ouvrant le fichier et en lisant son contenu dans la chaîne du nom d'utilisateur.

Chargement de l'éditeur…
Afficher l'indice

Ajoutez le caractère `?` après`File::open(...)`et après`username_file.read_to_string(...)` pour propager les erreurs.

Solution disponible après 3 tentatives

Exercice 2 : Analyser et traiter un nombre

Exercice#rust.m7.l2.e2
Tentatives : 0Chargement…

Écrivez une fonction appelée parse_and_double qui prend en entrée une référence de chaîne &str et renvoie un Result<i32, std::num::ParseIntError>. La fonction doit analyser la chaîne avec val.parse::<i32>() en utilisant ? pour propager l'erreur d'analyse, et en cas de succès, renvoyer la valeur doublée entre Ok.

Chargement de l'éditeur…
Afficher l'indice

Utilisez `val.parse::<i32>()?`pour convertir la chaîne en propageant l'erreur, puis retournez`Ok(num * 2)`.

Solution disponible après 3 tentatives

Exercice 3 : Définir une erreur personnalisée

Exercice#rust.m7.l2.e3
Tentatives : 0Chargement…

Définissez une structure vide appelée CustomError. Implémentez le trait std::fmt::Display en écrivant le message « Une erreur personnalisée s'est produite » dans la méthode fmt.

Chargement de l'éditeur…
Afficher l'indice

Déclarez `struct CustomError;`et implémentez Display en écrivant`write!(f, "Si e verificato un errore personalizzato")`dans la méthode`fmt`.

Solution disponible après 3 tentatives