Fehlerbehandlung in Rust: try/catch und mehr – vollständiger Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Fehlerbehandlung in Rust: Verzicht auf try/catch zugunsten von Sicherheit



Im Gegensatz zu Python oder Java gibt es in Rust keine klassische try/catch-Konstruktion. Die Sprachentwickler haben einen anderen Weg gewählt und die Fehlerbehandlung zum Teil des Typsystems gemacht. Dies ist keine Willkür, sondern eine grundlegende Entscheidung, die es ermöglicht, Speichersicherheit und Vorhersagbarkeit des Programmablaufs bereits zur Kompilierzeit zu garantieren. In diesem Artikel werden wir alle Methoden der Fehlerbehandlung in Rust durchgehen: von den grundlegenden Result und Option bis hin zu fortgeschrittenen Techniken mit dem ?-Operator und benutzerdefinierten Fehlertypen.



1. Die zwei Haupttypen: Result und Option



In Rust werden Fehler in zwei Lager unterteilt: behebbare (werden über Result behandelt) und nicht behebbare (führen zu panic!). Außerdem gibt es den Typ Option für Fälle, in denen ein Wert fehlen kann.



Der Typ Result



Result<T, E> ist eine Aufzählung (enum), die entweder Ok(T) (Erfolg mit Daten) oder Err(E) (Fehler mit Beschreibung) sein kann. Dies ist das wichtigste Werkzeug zur Behandlung erwarteter Fehler: Ein-/Ausgabefehler, Parsing-Fehler, Netzwerkanfragen.



use std::fs::File;use std::io::Read;

fn read_file_content(path: &str) -> Result<String, std::io::Error> { let mut file = File::open(path)?; let mut content = String::new(); file.read_to_string(&mut content)?; Ok(content)}


Der Typ Option



Option<T> ist ein weiteres enum, das die Werte Some(T) (Wert vorhanden) oder None (kein Wert) annimmt. Es wird verwendet, wenn das Fehlen von Daten eine normale Situation und kein Fehler ist.



fn find_user(id: u32) -> Option<String> {    let users = vec!["Alice".to_string(), "Bob".to_string()];    users.get(id as usize).cloned()}

fn main() { match find_user(0) { Some(name) => println!("Benutzer gefunden: {}", name), None => println!("Benutzer nicht gefunden"), }}


2. Der ?-Operator – elegante Alternative zu try/catch



Wenn Rust ein try/catch hätte, wäre es umständlich. Stattdessen bietet die Sprache den ?-Operator. Er funktioniert so: Wenn das Ergebnis Ok ist, wird der Wert extrahiert und weitergegeben; wenn Err, wird der Fehler sofort aus der Funktion zurückgegeben.



use std::num::ParseIntError;

fn parse_and_double(input: &str) -> Result<i32, ParseIntError> { let value: i32 = input.parse()?; // bei Fehler sofort return Err Ok(value * 2)}

fn main() { match parse_and_double("42") { Ok(result) => println!("Ergebnis: {}", result), Err(e) => println!("Parsing-Fehler: {}", e), }}


Der ?-Operator kann nur in Funktionen verwendet werden, die Result oder Option zurückgeben. Dies zwingt den Entwickler, explizit anzugeben, dass die Funktion mit einem Fehler enden kann – im Gegensatz zu Ausnahmen in Python, die an jeder Stelle „auftauchen“ können.



3. Wann panic! und unwrap verwendet werden sollten



Nicht alle Fehler müssen behandelt werden. panic! ist ein Makro für nicht behebbare Fehler. Es stoppt das Programm und entrollt den Stack (stack unwind). Verwenden Sie es nur in Ausnahmesituationen:



  • Kritische Zustände: Verletzung von Invarianten, die nicht behoben werden können.
  • Beispiele und Prototypen: in Lehrcode oder Einweg-Skripten.
  • Tests: um zu überprüfen, ob der Code an erwarteten Stellen abstürzt.


fn divide(a: i32, b: i32) -> i32 {    if b == 0 {        panic!("Division durch Null! a={}, b={}", a, b);    }    a / b}


unwrap() und expect()

Blogs

Buchempfehlungen