Robust felhantering med `Result`
Implementera idiomatisk felhantering med enumen `Result`, operatorn `?` och anpassade feltyper för motståndskraftiga applikationer.
Robust felhantering med `Result` är en gratis lektion i Lär dig programmera i Rust på CoddyKit. Detta är lektion 3 av 3. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Lär dig programmera i Rust, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Lär dig programmera i Rust innehåller totalt 3 lektioner.
Hantera fel i Rust
Fel är en del av programmering. I Rust skiljer vi mellan två huvudtyper: återställningsbara och oåterställningsbara fel.
- Oåterställningsbara fel signalerar vanligtvis buggar och får programmet att avslutas med
panic!. - Återställningsbara fel betyder att något gick fel men kan hanteras, till exempel att en fil inte hittades.
Rust hjälper dig att hantera återställningsbara fel på ett smidigt sätt.
`panic!` jämfört med `Result`
När ett oåterställningsbart fel inträffar anropar Rust makrot panic!. Det rullar tillbaka stacken och avslutar programmet, vanligtvis efter att ha skrivit ut ett felmeddelande.
För återställningsbara fel använder Rust enumen Result. Den talar om huruvida en operation lyckades (Ok) eller misslyckades (Err), så att programmet kan avgöra vad det ska göra härnäst.
Enumen `Result`
Enumen Result definieras konceptuellt så här:
enum Result<T, E> {
Ok(T),
Err(E),
}
Trepresenterar typen för värdet som returneras vid framgång.Erepresenterar typen för felet som returneras vid misslyckande.
Det är ett kraftfullt sätt att uttryckligen ange att en funktion kan misslyckas.
Matchning på `Result`
Det vanligaste sättet att hantera en Result är att använda ett match-uttryck. Det gör att du kan köra olika kodblock beroende på om Result är Ok eller Err.
Prova att köra det här exemplet, som försöker tolka ett tal:
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),
}
}Packa upp Result (varsamt!)
Ibland är du säker på att en operation inte kommer att misslyckas, eller så vill du att programmet ska krascha om den gör det. Metoder som unwrap() och expect() hämtar Ok-värdet.
unwrap(): ReturnerarOk-värdet eller orsakar panic om värdet ärErr.expect("message"): Fungerar somunwrap(), men låter dig ange ett eget panic-meddelande.
Använd dessa sparsamt, främst i tester eller när ett misslyckande verkligen inte kan återställas.
Introduktion till operatorn `?`
Att skriva match-satser för varje Result kan bli upprepande. Operatorn ? är en kortare genväg för att vidarebefordra fel.
När ? placeras efter ett uttryck som returnerar en Result gör den två saker:
- Om
ResultärErrreturnerar den omedelbartErrfrån den aktuella funktionen. - Om
ResultärOkpackar den uppOk-värdet och fortsätter körningen.
Operatorn `?` i praktiken
Operatorn ? gör funktioner som kan misslyckas mycket enklare att skriva. Kom ihåg att funktionen som använder ? själv måste returnera en Result (eller Option).
Se hur ? förenklar felhanteringen i det här exemplet där en fil läses:
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();
}Egna feltyper
Ibland är de inbyggda feltyperna inte tillräckligt specifika. Du kan definiera egna feltyper med enum för att representera olika sätt som programmet kan misslyckas på.
Det gör felmeddelandena tydligare och låter anropande kod hantera specifika fel på olika sätt.
Ett vanligt mönster är att skapa en enum som listar alla möjliga fel som en funktion eller modul kan generera.
Få `?` att fungera med egna fel
För att operatorn ? automatiskt ska kunna konvertera ett fel på lägre nivå (till exempel io::Error) till din egen feltyp måste din egendefinierade fel-enum implementera traiten From för felet på lägre nivå.
Det talar om för Rust hur en feltyp ska konverteras till en annan och gör vidarebefordran av fel smidig.
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),
}
}Kontrollera din förståelse
Studera följande Rust-kod. Vad blir resultatet om filen data.txt INTE finns?
Sammanfattning: Robust felhantering
Du behärskar nu robust felhantering i Rust!
- Enumen
Result: Skiljer mellanOk(T)vid framgång ochErr(E)vid misslyckande. match: Det grundläggande sättet att hantera varianter avResult.- Operatorn
?: En kraftfull genväg för att vidarebefordraErr-värden upp genom anropsstacken. - Egna fel: Definiera egna feltyper med enum för tydlighet och specifik hantering.
- Traiten
From: Möjliggör smidig konvertering av fel på lägre nivå till dina egna feltyper när du använder?.
Härnäst utforskar du avancerade funktioner i typsystemet!
Lär dig Rust med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 39
- Lektioner
- 144
Vanliga frågor
Är lektionen ”Robust felhantering med `Result`” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Lär dig programmera i Rust, inklusive ”Robust felhantering med `Result`”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Lär dig programmera i Rust innehåller totalt 3 lektioner.
Vad lär jag mig i ”Robust felhantering med `Result`”?
Implementera idiomatisk felhantering med enumen `Result`, operatorn `?` och anpassade feltyper för motståndskraftiga applikationer. Ni övar på Lär dig programmera i Rust med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Lär dig programmera i Rust?
Du behöver inga förkunskaper. Utbildningen i Lär dig programmera i Rust på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 3.
Hur lång tid tar lektionen ”Robust felhantering med `Result`”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Lär dig programmera i Rust-lektionen?
Ja. Varje Lär dig programmera i Rust-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Organisera kod med moduler
- Hantera beroenden med crates
- Robust felhantering med `Result`