Direkt zum Hauptinhalt springen
eLearner.app
Modul 7 · Lektion 2 von 214/14 im Kurs~15 min
Lektionen des Moduls (2/2)

Fehlerbehandlung und der ?-Operator

Die Rust-Philosophie empfiehlt, die Möglichkeit von Fehlern explizit zu erkennen und den Code so zu strukturieren, dass er damit umgeht, bevor das Programm kompiliert wird.

Fehler in Rust werden in zwei Hauptkategorien unterteilt: nicht behebbare Fehler (verursacht sofortiges Hängenbleiben über die panic!-Panik) und behebbare Fehler (behandelt über den Typ Result<T, E>).


Der Ergebnistyp<T, E> und der Mustervergleich

Die meisten behebbaren Fehler geben einen Typ Result<T, E> zurück, der eine Aufzählung ist, die wie folgt definiert ist:

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

Wir können den Mustervergleich verwenden, um das Ergebnis zu überprüfen:

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),
    };
}

Fehlerausbreitung mit dem Operator ?

Wenn wir eine Funktion implementieren, möchten wir den Fehler oft nicht direkt darin behandeln, sondern den Fehler an den Aufrufer zurückgeben, damit er entscheiden kann, was zu tun ist. Dieser Vorgang wird Fehlerausbreitung genannt.

Rust stellt den Operator ? als syntaktische Abkürzung für die Fehlerausbreitung bereit. Wenn der Wert eines Result Ok ist, wird der Wert innerhalb von Ok vom Ausdruck zurückgegeben; Wenn es Err ist, wird der Fehler Err von der gesamten aktuellen Funktion zurückgegeben, als ob wir einen return Err(...) verwendet hätten.

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] Der Operator ? kann nur in Funktionen verwendet werden, die einen Typ zurückgeben, der mit dem Wert kompatibel ist, auf den er angewendet wird (typischerweise Result, Option oder Typen, die FromResidual implementieren).


Benutzerdefinierte Fehler

Wir können unsere eigenen Fehlertypen definieren, indem wir das Merkmal std::fmt::Display (und optional std::error::Error) implementieren, um eine für Menschen lesbare Darstellung des Fehlers bereitzustellen:

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 {}

Probieren Sie es selbst aus

Übung 1: Eine Datei mit dem ? lesen Operator

Übung#rust.m7.l2.e1
Versuche: 0Wird geladen…

Vervollständigen Sie die Funktion „read_username_from_file“, um das „?“ zu verwenden. Operator. um Fehler, die durch das Öffnen der Datei und das Einlesen ihres Inhalts entstehen, in die Benutzernamenzeichenfolge zu übertragen.

Editor wird geladen…
Hinweis anzeigen

Fügen Sie das Zeichen `?` nach `File::open(...)` und nach `username_file.read_to_string(...)` hinzu, um Fehler weiterzugeben.

Lösung nach 3 Versuchen verfügbar

Übung 2: Eine Zahl analysieren und verarbeiten

Übung#rust.m7.l2.e2
Versuche: 0Wird geladen…

Schreiben Sie eine Funktion namens parse_and_double, die als Eingabe eine Zeichenfolgenreferenz &str verwendet und ein Ergebnis<i32, std::num::ParseIntError> zurückgibt. Die Funktion sollte die Zeichenfolge mit val.parse::<i32>() unter Verwendung von ? um den Parsing-Fehler zu verbreiten und bei Erfolg den doppelten Wert zurückzugeben, der in Ok eingeschlossen ist.

Editor wird geladen…
Hinweis anzeigen

Verwenden Sie `val.parse::<i32>()?`, um die Zeichenfolge durch Weitergabe des Fehlers zu konvertieren, und geben Sie dann `Ok(num * 2)` zurück.

Lösung nach 3 Versuchen verfügbar

Übung 3: Definieren Sie einen benutzerdefinierten Fehler

Übung#rust.m7.l2.e3
Versuche: 0Wird geladen…

Definieren Sie eine leere Struktur namens CustomError. Implementieren Sie das Merkmal std::fmt::Display dafür, indem Sie die Meldung „Ein benutzerdefinierter Fehler ist aufgetreten“ in die fmt-Methode schreiben.

Editor wird geladen…
Hinweis anzeigen

Deklarieren Sie `struct CustomError;`und implementieren Sie Display, indem Sie `write!(f, "Si e verificato un errore personalizzato")`in die Methode `fmt` schreiben.

Lösung nach 3 Versuchen verfügbar