Die Verwendung des Typs Result ist einer der Schlüsselansätze zur Fehlerbehandlung in Rust geworden. Historisch wurden in vielen Sprachen—zum Beispiel C—Fehler häufig durch spezielle Rückgabewerte oder globale Variablen signalisiert, was zu häufigen Fehlern bei der Ignorierung dieser Signale führte. Rust hat den Weg der expliziten Typisierung von Fehlern mit dem Enum Result<T, E> eingeschlagen, was es unmöglich macht, einen Fehler versehentlich zu ignorieren — der Compiler zwingt zur Bearbeitung beider Zweige (Erfolg und Misserfolg).
Problem: Es war erforderlich, die Fehlerbehandlung so sicher und lesbar wie möglich zu gestalten, versteckte Fehler auszuschließen und die Zuverlässigkeit des Codes zu erhöhen, ohne Ausnahmen verwenden zu müssen.
Lösung: Result<T, E> ist eine Enum mit zwei Varianten: Ok(T) bei Erfolg und Err(E) bei Fehler. Dies zwingt dazu, Fehler explizit zu behandeln, oder sie mit unwrap absichtlich zu ignorieren, oder auf panics zu warten. Darüber hinaus macht der Operator ? gängige Fehlerweiterleitungsmuster kurz und prägnant.
Beispielcode:
use std::fs::File; use std::io::{self, Read}; fn read_file(path: &str) -> Result<String, io::Error> { let mut file = File::open(path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) }
Hauptmerkmale:
?.Kann man den Operator ? immer für die automatische Weiterleitung von Fehlern nach oben verwenden?
Nein, nur wenn der Fehlertyp der Funktion mit dem Typ des Ausdrucks rechts von ? übereinstimmt. Wenn die Typen nicht kompatibel sind, muss eine explizite Fehlerumwandlung mit der Methode .map_err() oder einem eigenen Typ vorgenommen werden.
Beispielcode:
fn f() -> Result<(), String> { let _f = File::open("foo").map_err(|e| e.to_string())?; Ok(()) }
Kann man das Ergebnis von Result ungenutzt lassen, wenn man sich einfach nicht für Fehler interessiert?
Nein, der Compiler gibt eine Warnung oder einen Fehler aus, wenn das Ergebnis des Typs Result nicht verarbeitet wird. Entweder ruft man .unwrap() auf oder ruft explizit .ok()/.err()/let _ = ... auf oder protokolliert den Fehler richtig.
Was passiert, wenn man .unwrap() auf Result mit einem Fehler aufruft?
Es wird ein panic! ausgelöst und die Ausführung des Programms wird unterbrochen, was normalerweise zu einem Absturz führt. Daher ist unwrap() nur zulässig, wenn der Erfolg garantiert ist.
unwrap() im Produktionscode (unsicher)let _ = ...;) ohne Protokollierung?, was zu verwirrenden Kompilierungsfehlern führtEin Entwickler beschloss, die Konfiguration aus einer Datei zu lesen und verwendete unwrap() auf dem Ergebnis des Lesens.
Vorteile:
Nachteile:
Fehler beim Lesen der Konfiguration werden protokolliert und mit Hilfe von Result + Operator ? nach oben im Call-Stack weitergeleitet.
Vorteile:
Nachteile: