Gestion robuste des erreurs avec `Result`
Mettez en œuvre une gestion idiomatique des erreurs à l’aide de l’énumération `Result`, de l’opérateur `?` et de types d’erreur personnalisés pour créer des applications résilientes.
Gestion robuste des erreurs avec `Result` est une leçon Learn Rust Coding gratuite sur CoddyKit. Ceci est la leçon 3 sur 3. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Learn Rust Coding, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Learn Rust Coding comprend 3 leçons au total.
Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.
Handling Errors in Rust
Errors are a part of programming. In Rust, we distinguish between two main types: recoverable and unrecoverable errors.
- Unrecoverable errors usually signal bugs, causing the program to stop with
panic!. - Recoverable errors mean something went wrong but can be handled, like a file not found.
Rust helps you deal with recoverable errors gracefully.
`panic!` vs `Result`
When an unrecoverable error occurs, Rust calls the panic! macro. This unwinds the stack and exits your program, usually printing an error message.
For recoverable errors, Rust uses the Result enum. This enum tells you if an operation succeeded (Ok) or failed (Err), letting your program decide what to do next.
The `Result` Enum
The Result enum is defined conceptually as:
enum Result<T, E> {
Ok(T),
Err(E),
}
Trepresents the type of value returned on success.Erepresents the type of error returned on failure.
It's a powerful way to explicitly state that a function might fail.
Matching on `Result`
The most common way to handle a Result is using a match expression. This allows you to execute different code blocks based on whether the Result is Ok or Err.
Try running this example that attempts to parse a number:
fn parse_and_add(text: &str) -> Result<i32, std::num::ParseIntError> {
text.parse::<i32>()
}
fn main() {
let num_str = "123";
let result = parse_and_add(num_str);
match result {
Ok(num) => println!("Parsed number: {}", num),
Err(e) => println!("Error parsing: {}", e),
}
let bad_str = "abc";
let bad_result = parse_and_add(bad_str);
match bad_result {
Ok(num) => println!("Parsed number: {}", num),
Err(e) => println!("Error parsing: {}", e),
}
}Unwrapping Results (Carefully!)
Sometimes you might be certain an operation won't fail, or you want your program to crash if it does. Methods like unwrap() and expect() extract the Ok value.
unwrap(): Returns theOkvalue or panics if it'sErr.expect("message"): Same asunwrap()but lets you provide a custom panic message.
Use these sparingly, mainly in tests or when failure is truly unrecoverable.
Introducing the `?` Operator
Writing match statements for every Result can get repetitive. The ? operator provides a concise shortcut for error propagation.
When placed after an expression that returns a Result, ? does two things:
- If the
ResultisErr, it immediately returns theErrfrom the current function. - If the
ResultisOk, it unwraps theOkvalue and continues execution.
`?` Operator in Action
The ? operator makes functions that might fail much cleaner to write. Remember, the function using ? must itself return a Result (or Option).
Observe how ? simplifies error handling in this file reading example:
use std::fs::File;
use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut f = File::open("hello.txt")?; // Propagates error if file not found
let mut s = String::new();
f.read_to_string(&mut s)?; // Propagates error if read fails
Ok(s)
}
fn main() {
// Create a dummy file for the example to work
// In a real scenario, this file might not exist
std::fs::write("hello.txt", "CoddyKit User").unwrap();
match read_username_from_file() {
Ok(username) => println!("Username: {}", username),
Err(e) => println!("Error reading username: {}", e),
}
// Clean up the dummy file
std::fs::remove_file("hello.txt").unwrap();
}Custom Error Types
Sometimes, built-in error types aren't specific enough. You can define your own custom error types using enums to represent different failure modes of your application.
This makes your error messages clearer and allows callers to handle specific errors differently.
A common pattern is to create an enum that lists all possible errors a function or module can produce.
Making `?` Work with Custom Errors
For the ? operator to automatically convert a lower-level error (like io::Error) into your custom error type, your custom error enum must implement the From trait for that lower-level error.
This tells Rust how to convert one error type into another, making error propagation seamless.
use std::io;
use std::fs::File;
use std::io::Read;
#[derive(Debug)]
enum MyError {
Io(io::Error),
Parse(std::num::ParseIntError)
}
impl From<io::Error> for MyError {
fn from(error: io::Error) -> Self {
MyError::Io(error)
}
}
impl From<std::num::ParseIntError> for MyError {
fn from(error: std::num::ParseIntError) -> Self {
MyError::Parse(error)
}
}
fn read_config(path: &str) -> Result<i32, MyError> {
let mut file = File::open(path)?; // io::Error converted to MyError::Io
let mut contents = String::new();
file.read_to_string(&mut contents)?; // io::Error converted to MyError::Io
let value = contents.trim().parse::<i32>()?; // ParseIntError converted to MyError::Parse
Ok(value)
}
fn main() {
// Create a dummy file for the example
std::fs::write("config.txt", "123").unwrap();
match read_config("config.txt") {
Ok(val) => println!("Config value: {}", val),
Err(e) => println!("Failed to read config: {:?}", e),
}
std::fs::remove_file("config.txt").unwrap(); // Clean up
// Example with a non-existent file
match read_config("non_existent.txt") {
Ok(val) => println!("Config value: {}", val),
Err(e) => println!("Failed to read config: {:?}", e),
}
}Check Your Understanding
Consider the following Rust code snippet. What will be the output if the file data.txt does NOT exist?
Recap: Robust Error Handling
You've mastered robust error handling in Rust!
ResultEnum: Distinguishes betweenOk(T)for success andErr(E)for failure.match: The fundamental way to handleResultvariants.?Operator: A powerful shortcut for propagatingErrvalues up the call stack.- Custom Errors: Define your own error types using enums for clarity and specific handling.
FromTrait: Enables seamless conversion of lower-level errors into your custom error types when using?.
Next, explore advanced type system features!
Questions Fréquemment Posées
La leçon « Gestion robuste des erreurs avec `Result` » est-elle gratuite ?
Oui — le texte complet de « Gestion robuste des erreurs avec `Result` » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Learn Rust Coding, passe à CoddyKit PRO. Le cours Learn Rust Coding comprend 3 leçons au total.
Qu'est-ce que j'apprendrai dans « Gestion robuste des erreurs avec `Result` » ?
Mettez en œuvre une gestion idiomatique des erreurs à l’aide de l’énumération `Result`, de l’opérateur `?` et de types d’erreur personnalisés pour créer des applications résilientes. Tu pratiques Learn Rust Coding avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Learn Rust Coding ?
Aucune expérience préalable n'est requise. Learn Rust Coding sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 3.
Combien de temps prend la leçon « Gestion robuste des erreurs avec `Result` » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Learn Rust Coding ?
Oui. Chaque leçon Learn Rust Coding inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Organiser le code avec des modules
- Gérer les dépendances avec les caisses
- Gestion robuste des erreurs avec `Result`