Les erreurs sont inévitables et peuvent survenir pour diverses raisons, de la saisie invalide de l’utilisateur aux pannes de réseau, en passant par les dysfonctionnements matériels ou les bogues de programmation. La gestion des erreurs est le processus de détection, de signalement et de récupération de ces erreurs afin d’éviter les plantages de programmes ou la corruption de données.
Une gestion efficace des erreurs est essentielle en Rust. Elle vous permet de créer des applications robustes et fiables, capables de gérer des erreurs et des défaillances inattendues. Les mécanismes de gestion des erreurs de Rust vous permettent de développer des programmes résistants et sûrs qui sont plus faciles à maintenir.
Les types d’erreurs en Rust
Rust dispose d’un riche système de types que vous pouvez utiliser pour gérer les erreurs de manière efficace, en fonction de leurs types. Les avantages du riche système de types d’erreurs de Rust par rapport aux approches traditionnelles de gestion des erreurs ne peuvent pas être sous-estimés. Le système de types d’erreurs améliore la sécurité des types, la composabilité, l’expressivité et le débogage.
Voici une liste des types d’erreur courants en Rust :
- L’erreur std::io::Error représente les erreurs d’E/S telles que fichier introuvable, permission refusée ou fin de fichier atteinte.
- Le type std::num::ParseIntError représente les erreurs qui surviennent lors des opérations d’analyse des chaînes de caractères entiers.
- Le type std::option::NoneError Ce type représente les erreurs dues au déballage d’options vides.
- Le type std::result::Result<T, E> ; est un type générique Result que vous pouvez utiliser pour représenter n’importe quelle erreur.
Chaque type d’erreur possède son propre ensemble de méthodes et de caractéristiques permettant de la traiter de manière spécifique.
Voici un exemple de gestion d’erreur en Rust pour une opération de lecture de fichier :
use std::fs::File;
use std::io::Read;
fn read_file(path: &str) -> Result<String, std::io::Error> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
L’erreur lire_le_fichier lit le contenu du fichier dans le chemin spécifié et le renvoie sous forme de chaîne de caractères. Elle renvoie un std::io::Error si l’opération d’ouverture ou de lecture du fichier échoue. Les ? propage l’erreur et la renvoie sous la forme d’un message d’erreur Résultat.
Mécanismes de gestion d’erreurs en Rust
Les mécanismes de gestion des erreurs sont l’une des principales caractéristiques qui contribuent à la sécurité de Rust. Il existe quatre mécanismes principaux de gestion des erreurs en Rust : le Résultat le type de Option l’option panique ! et la macro Erreur trait.
Les types Result et Option permettent une gestion structurée des erreurs. Vous pouvez utiliser la macro panic ! pour gérer les erreurs irrécupérables. Le trait Error vous permet de définir des types d’erreurs et une gestion d’erreurs personnalisés.
Le type de résultat
Le Résultat est un type intégré représentant le résultat d’une opération qui peut échouer. Il existe deux variantes : le type Ok qui représente un succès et contient une valeur, et Errqui représente un échec et contient une valeur d’erreur.
Voici comment utiliser le type Result pour ouvrir un fichier et lire son contenu :
use std::fs::File;
use std::io::prelude::*;
fn read_file(file_path: &str) -> Result<String, std::io::Error> {
let mut file = File::open(file_path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
fn main() {
let result = read_file("file.txt");
match result {
Ok(contents) => println!("{}", contents),
Err(e) => println!("Error: {}", e),
}
}
Le type lire_le_fichier prend le chemin du fichier et renvoie un Result<String, std::io::Error> ; erreur. Si l’opération de lecture ou d’ouverture du fichier échoue, la fonction renvoie la valeur Err . Sinon, la fonction renvoie la valeur Ok valeur. Dans le principal la fonction correspondre gère la déclaration de Résultat et imprime le résultat en fonction de la situation de l’opération sur le fichier.
Le type d’option
Le type d’option Option est un type intégré représentant la présence ou l’absence d’une valeur. Le type Option a deux variantes. Certains représente une valeur, et Aucun représente l’absence de valeur.
Voici comment vous pouvez utiliser la fonction Option pour récupérer le premier élément d’un vecteur.
fn get_first_element<T: Clone>(vec: Vec<T>) -> Option<T> {
if vec.is_empty() {
None
} else {
Some(vec.first().unwrap().clone())
}
}
fn main() {
let vec = vec![1, 2, 3];
let result = get_first_element(vec);
match result {
Some(element) => println!("{}", element),
None => println!("The vector is empty."),
}
}
La fonction get_first_element renvoie un Option<T> ; type. Si le vecteur est vide, la fonction renvoie Aucun; sinon, la fonction renvoie Quelques contenant le premier élément du vecteur. Dans le principal la fonction correspondre gère la déclaration de Option valeur. Si la valeur L’option évalue à Certainsla fonction imprime le premier élément. Sinon, la fonction affiche un message indiquant que le vecteur est vide.
La macro panic ! Macro
La panique ! La macro fournit une fonctionnalité pour gérer les erreurs irrécupérables en Rust. Lors de l’appel de la macro panique ! elle affiche un message d’erreur et met fin au programme.
Voici un exemple d’utilisation de la macro panic ! pour indiquer qu’une fonction a des arguments non valides.
fn divide(dividend: f64, divisor: f64) -> f64 {
if divisor == 0.0 {
panic!("The divisor cannot be zero.");
}
dividend / divisor
}
fn main() {
let result = divide(4.0, 0.0);
println!("{}", result);
}
La macro diviser vérifie si le diviseur est nul ; si c’est le cas, la fonction appelle la fonction panique ! avec un message d’erreur ; sinon, la fonction calcule et renvoie le résultat.
La fonction principal appelle la fonction divide avec des arguments non valides pour déclencher la fonction panique ! macro.
Voici le message d’erreur :
Le trait d’erreur
L’erreur Erreur est un trait intégré qui définit le comportement des types d’erreur. Le trait Erreur Le trait fournit une fonctionnalité permettant de définir des types d’erreurs et des traitements d’erreurs personnalisés.
Voici un exemple de définition d’un type d’erreur personnalisé qui représente une erreur de fichier non trouvé.
use std::error::Error;
use std::fmt;
use std::io::Read;
#[derive(Debug)]
struct FileNotFound(String);
impl fmt::Display for FileNotFound {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "File not found: {}", self.0)
}
}
impl Error for FileNotFound {}
fn read_file(file_path: &str) -> Result<String, Box<dyn Error>> {
let mut file = std::fs::File::open(file_path).map_err(|e| FileNotFound(format!("{}", e)))?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
fn main() {
let result = read_file("file.txt");
match result {
Ok(contents) => println!("{}", contents),
Err(e) => println!("Error: {}", e),
}
}
Le type d’erreur personnalisé est le type Fichier introuvable struct. Le type contient un chemin d’accès au fichier, et l’élément FileNotFound met en œuvre le type Affichage Les messages d’erreur sont plus faciles à comprendre et le message d’erreur est plus facile à lire. Erreur pour indiquer qu’il s’agit d’un type d’erreur.
Dans le trait lire_le_fichier la fonction FileNotFound représente une erreur de fichier non trouvé, et l’élément map_err convertit l’erreur std::io::Error en une erreur FileNotFound. Enfin, la boîte<dyn Error> ; permet à la fonction de renvoyer n’importe quel type implémentant le trait Error.
Le type principal appelle la fonction lire_le_fichier avec le chemin d’accès au fichier et, si elle trouve le fichier, affiche son contenu sur la console. Sinon, elle affiche le message d’erreur.
Voici le résultat pour un fichier qui n’existe pas :
Vous pouvez compter sur le modèle de propriété de Rust pour la sécurité des programmes
Associé au magnifique mécanisme de gestion des erreurs de Rust, Rust utilise également un modèle de propriété qui permet de s’assurer que vos programmes sont sûrs en termes de mémoire.
Rust garantit les règles de propriété à l’aide d’un vérificateur d’emprunt au moment de la compilation, avant que votre programme ne s’exécute.