In Rust gibt es keine gewohnten Ausnahmen (exceptions) wie in Java oder C++; stattdessen werden die Wrapper-Typen Result und Option zur Rückgabe von Fehlern verwendet.
Result<T, E> — speichert entweder einen Wert (Ok(T)) oder einen Fehler (Err(E)). Es wird normalerweise für Operationen verwendet, die möglicherweise nicht korrekt ausgeführt werden können (z. B. Dateieingabe und -ausgabe).
Option<T> — für optionale Werte: entweder Some(T) oder None, ohne Informationen über den Fehler. Beispiel:
fn divide(x: f64, y: f64) -> Option<f64> { if y == 0.0 { None } else { Some(x / y) } }
In Rust gibt es keine Ausnahmen im Stil von try/catch, um einen transparenten, kontrollierten Fehlerfluss zu gewährleisten und keinen Garbage Collector oder Unwind-Engine zur Unterstützung von Ausnahmen zu benötigen.
Warum kann panic! nicht zur normalen Fehlerverarbeitung verwendet werden?
Antwort: panic! beendet den Ausführungsfluss, lässt keine Wiederherstellung zu und führt zu unwinding/abort. Wenn Fehler jedoch über Result zurückgegeben werden, kann die aufrufende Seite sie verarbeiten. Beispiel:
fn foo() -> Result<(), String> { Err("Etwas ist schiefgegangen".to_string()) } // statt fn foo() { panic!("Etwas ist schiefgegangen"); }
Geschichte
In einem Mikrodienst zur Bildverarbeitung verwendete der Entwickler
panic!zur Verarbeitung aller Notfälle. Dies führte dazu, dass der Dienst bei jedem Fehler abrupt beendet wurde, anstatt eine korrekte HTTP-Antwort an den Client mit Fehlermeldungen zurückzugeben.
Geschichte
In einem CLI-Tool wurde
unwrap()für alle Eingaben und Ausgaben verwendet, ohne mögliche Fehler zu verarbeiten. Infolgedessen endete das Programm bei einem Fehler im Dateisystem einfach ohne eine Nachricht oder Diagnose.
Geschichte
In einem Analyse-Service versuchte man, Option für jede kleine Fehlermeldung zu verwenden, wodurch die Informationen über die Fehler verloren gingen und das Debuggen erschwert wurde. Nach dem Umstieg auf Result mit Fehler-Enums wurde es einfacher, Fehler zu finden und zu beheben.