Direct naar de hoofdinhoud
Module 7 · Les 2 van 214/14 in de cursus~15 min
Modulelessen (2/2)

Foutafhandeling en de ? Exploitant

De filosofie van Rust moedigt je aan om de mogelijkheid van fouten expliciet te onderkennen en je code zodanig te structureren dat deze wordt afgehandeld voordat het programma wordt gecompileerd.

Fouten in Rust zijn onderverdeeld in twee hoofdcategorieën: onherstelbare fouten (die onmiddellijke beëindiging veroorzaken via de macro panic!) en herstelbare fouten (beheerd met het type Result<T, E>).


Het resultaat<T, E> Type- en patroonmatching

De meeste herstelbare fouten retourneren het type Result<T, E>, een opsomming die is gedefinieerd als:

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

We kunnen patroonmatching gebruiken om het resultaat te inspecteren:

Rust
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!("Problem opening the file: {:?}", error),
    };
}

Foutpropagatie met de operator ?

Bij het implementeren van een functie willen we, in plaats van de fout direct daarin af te handelen, de fout vaak terugsturen naar de aanroeper, zodat deze kan beslissen wat hij moet doen. Dit proces wordt foutvoortplanting genoemd.

Rust biedt de operator ? als een syntactische snelkoppeling om fouten door te geven. Als de waarde van een Result Ok is, wordt de innerlijke waarde van Ok geretourneerd door de expressie; als het Err is, wordt de fout Err geretourneerd door de gehele huidige functie alsof we een return Err(...) hadden gebruikt.

Rust
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)
}

[!BELANGRIJK] De operator ? kan alleen worden gebruikt in functies die een type retourneren dat compatibel is met de waarde waarop het wordt toegepast (meestal Result, Option, of typen die FromResidual implementeren).


Aangepaste fouten

We kunnen onze eigen aangepaste fouttypen definiëren door de eigenschap std::fmt::Display (en optioneel std::error::Error) te implementeren om een ​​voor mensen leesbare weergave van de fout te bieden:

Rust
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, "Error: {}", self.details)
    }
}

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

Probeer het zelf

Oefening 1: Een bestand lezen met de ? exploitant

Oefening#rust.m7.l2.e1
Pogingen: 0Laden…

Voltooi de functie read_username_from_file zodat deze de ? operator om fouten door te geven die worden gegenereerd door het openen van het bestand en het lezen van de inhoud ervan in de gebruikersnaamreeks.

Editor laden…
Toon hint

Voeg het teken `?` toe na`File::open(...)`en na`username_file.read_to_string(...)` om fouten door te geven.

Oplossing beschikbaar na 3 pogingen

Oefening 2: Een getal ontleden en verdubbelen

Oefening#rust.m7.l2.e2
Pogingen: 0Laden…

Schrijf een functie met de naam parse_and_double die een tekenreeksreferentie &str accepteert en een Resultaat<i32, std::num::ParseIntError> retourneert. De functie moet de tekenreeks parseren met behulp van val.parse::<i32>() met ? om parseerfouten door te geven en bij succes de dubbele waarde terug te geven, verpakt in Ok.

Editor laden…
Toon hint

Gebruik `val.parse::<i32>()?`om de string te parseren en de fout door te geven, en retourneer vervolgens `Ok(num \* 2)`.

Oplossing beschikbaar na 3 pogingen

Oefening 3: Een aangepaste fout definiëren

Oefening#rust.m7.l2.e3
Pogingen: 0Laden…

Definieer een lege structuur met de naam CustomError. Implementeer de std::fmt::Display-eigenschap ervoor door 'Si e verificato un errore personalizzato' te schrijven als de foutmelding in de fmt-methode.

Editor laden…
Toon hint

Declareer `struct CustomError;`en implementeer Display door`write!(f, "Si e verificato un errore personalizzato")`in de`fmt`methode te schrijven.

Oplossing beschikbaar na 3 pogingen