Skip to content
Zurück zu den Lernmaterialien

Modul 7 — Fehlerbehandlung

6. September 2026~3 min read
Lektion von 0/ abgeschlossen
Modul 7 — Fehlerbehandlung

Fehler typisieren: eigene Error-Enums

In Modul 5 kennengelernt: Result als Aufschrift "kann schiefgehen". Bisher war der Fehlerteil oft ein bloßer String — schnell, aber unstrukturiert. Ein eigenes Error-Enum macht jede Fehlerart zu einem benannten Wert, auf den Caller gezielt reagieren können:

#[derive(Debug, PartialEq)]
enum ParseError {
    InvalidLine(String),
    NotANumber(String),
}

fn parse_line(line: &str) -> Result<(String, u32), ParseError> {
    let (key, value) = line
        .split_once('=')
        .ok_or_else(|| ParseError::InvalidLine(line.to_string()))?;
    let num = value
        .trim()
        .parse::<u32>()
        .map_err(|_| ParseError::NotANumber(line.to_string()))?;
    Ok((key.trim().to_string(), num))
}

fn main() {
    match parse_line("timeout=30") {
        Ok((key, value)) => println!("{key} = {value}"),
        Err(e) => println!("Fehler: {e:?}"),
    }
}

Zwei Dinge passieren hier: ok_or_else verwandelt das Option von split_once in ein Result mit unserer Fehlerart, und map_err übersetzt den Fremdfehler des Parsers (ParseIntError) in unser Enum. Am Ende hat die ganze Funktion genau einen Fehlertyp.

Warum kein String als Fehlertyp?

  • Ein String kann alles behaupten — ein Enum hat fest definierte Varianten
  • Der Compiler erzwingt: wer matcht, behandelt jede Fehlerart (Exhaustivität)
  • Tests können Fehler exakt vergleichen (assert_eq! mit PartialEq)
  • Der Kontext (die Zeile) reist als Datenfeld im Variant mit

📝 Schnellprüfung

Was gewinnt ein Aufrufer durch das Error-Enum gegenüber einem String-Fehler?

Übung: die zweite Variante

🧩 Übung m7-l1-e1

🔮 Vorhersage: Was passiert beim Ausführen?

Editor wird geladen…
KI-Tutor (sokratisch — keine Komplettlösungen)

✅ Wichtige Erkenntnisse

Haken setzen, um deinen Lernfortschritt zu markieren:

    Lektion von 0/ abgeschlossen
    Modul 7 — Fehlerbehandlung

    Der ?-Operator: Fehler elegant weiterreichen

    Funktionen, die selbst nichts Sinnvolles mit einem Fehler anfangen können, reichen ihn nach oben weiter. Mit match wird das eine Match-Pyramide — mit dem ?-Operator eine Zeile pro Schritt:

    fn parse_number(s: &str) -> Result<i32, String> {
        s.trim()
            .parse::<i32>()
            .map_err(|_| String::from("keine Zahl"))
    }
    
    fn parse_pair(s: &str) -> Result<(i32, i32), String> {
        let (a, b) = s
            .split_once(',')
            .ok_or_else(|| String::from("Komma fehlt"))?;
        let x = parse_number(a)?;
        let y = parse_number(b)?;
        Ok((x, y))
    }
    
    fn main() -> Result<(), String> {
        let (x, y) = parse_pair("3,4")?;
        println!("Paar: {x}, {y}");
        Ok(())
    }
    

    Das ? bedeutet: Ok-Wert auspacken und weitermachen — oder den Fehler sofort aus der Funktion zurückgeben. Und sogar main darf Result zurückgeben: bei Err beendet sich das Programm mit einem Nicht-Null-Exitcode und druckt den Fehler — genau das, was Skripte und CI von einem CLI-Tool erwarten.

    Die drei ?-Regeln

    • Die umgebende Funktion muss selbst Result (oder Option) zurückgeben
    • Unterschiedliche Fehlertypen? ? konvertiert automatisch per From — oder du übersetzt vorher mit map_err
    • ? ist für Propagieren da; die Entscheidung (melden, retry, abbrechen) fällt ganz oben

    Probiere es selbst: schreibe eine Funktion doppelt(eingabe: &str), die die Eingabe als Zahl parst, verdoppelt und als Result zurückgibt — mit ? statt match.

    ? selbst ausprobierenBereit
    Editor wird geladen…

    📝 Schnellprüfung

    Was passiert, wenn parse_pair('7,x') mit ? läuft und parse_number('x') einen Fehler liefert?

    Übung: die Match-Pyramide abbauen

    🧩 Übung m7-l2-e1

    🔮 Vorhersage: Was passiert beim Ausführen?

    Editor wird geladen…
    KI-Tutor (sokratisch — keine Komplettlösungen)

    ✅ Wichtige Erkenntnisse

    Haken setzen, um deinen Lernfortschritt zu markieren:

      Lektion von 0/ abgeschlossen
      Modul 7 — Fehlerbehandlung

      Panic oder Result?

      Rust kennt zwei Fehlerwelten: Panic (unwideruflich: das Programm bricht ab) und Result (wiederherstellbar: der Caller entscheidet). Die Faust- regel der Praxis:

      • Panic — nur für Bugs und gebrochene Invarianten: ein Index außerhalb des Vec, eine Konfiguration, die schon beim Start belegt, dass der Code falsch ist
      • Result — für alles Erwartbare: fehlende Datei, kaputte Nutzereingabe, Timeout im Netzwerk
      fn lade_konfig(pfad: &str) -> Result<String, String> {
          match std::fs::read_to_string(pfad) {
              Ok(inhalt) => Ok(inhalt),
              Err(e) => Err(format!("Konfiguration nicht lesbar: {e}")),
          }
      }
      
      fn main() {
          match lade_konfig("app.conf") {
              Ok(inhalt) => println!("{} Bytes geladen", inhalt.len()),
              Err(msg) => {
                  eprintln!("Start abgebrochen: {msg}");
                  std::process::exit(1);
              }
          }
      }
      

      .expect("Kontext") ist der ehrlichere Bruder von .unwrap(): bei Panic druckt er den Kontext mit — aber beides gehört nicht auf Pfade, deren Scheitern du erwartest. Wenn es doch mal knallt, hilft:

      RUST_BACKTRACE=1 ./meinprogramm
      

      Der Backtrace zeigt die Aufrufliste im Panic-Moment — die Spur von der kaputten Stelle zurück zu dir.

      📝 Schnellprüfung

      Ein Nutzer gibt abc als Alter ein. Panic oder Result?

      Übung: kein Panic mehr

      🧩 Übung m7-l3-e1

      🔮 Vorhersage: Was passiert beim Ausführen?

      Editor wird geladen…
      KI-Tutor (sokratisch — keine Komplettlösungen)

      ✅ Wichtige Erkenntnisse

      Haken setzen, um deinen Lernfortschritt zu markieren:

        Lektion von 0/ abgeschlossen
        Modul 7 — Fehlerbehandlung

        Mini-Projekt: Config-Parser

        Alles aus dem Modul in einem Baustein: ein Parser für key=wert-Zeilen, der Fehler typisiert meldet und nie paniziert. Das Szenario:

        🏢 Praxis-Szenario: Die Server-Konfiguration

        Dein Server liest seine Einstellungen aus einer Textdatei: timeout=30, retries=5. Ein Kollege editiert die Datei von Hand — und vertippt sich. Bisher: das Programm paniziert beim Start mitten in der Nacht, ohne Hinweis, welche Zeile schuld war. Dein Vorschlag: ein Parser, der jede Zeile in ein Ergebnis mit klarer Fehlerart übersetzt und kaputte Zeilen benennt, statt unterzugehen.

        Die Übung baut genau diesen Parser — vom Enum bis zur Ausgabeschleife:

        🧩 Übung m7-l4-e1

        🔮 Vorhersage: Was passiert beim Ausführen?

        Editor wird geladen…
        KI-Tutor (sokratisch — keine Komplettlösungen)

        Was du in Modul 7 geschafft hast

        • Fehlerarten als Varianten — der Compiler zwingt zur vollständigen Behandlung
        • ? macht Propagieren zur One-Liner; main als Result nutzt Exitcodes
        • Panic ist die Ausnahme für Bugs — nicht die Norm für Fehler
        • Ein Parser, der kaputte Eingaben benennt statt abzustürzen

        ✅ Wichtige Erkenntnisse

        Haken setzen, um deinen Lernfortschritt zu markieren:

          Modul-Checkpoint

          Checkpoint: Modul 7

          Bestehensgrenze: 80 %. Der Versuch wird bewertet und zählt für das Modul-Gate.

          Bereit, dein Wissen zu testen?

          Probiere unsere Übungsprüfungen mit Hunderten von realistischen Fragen aus.

          Üben starten →

          This site uses essential cookies for Stripe payments. No tracking cookies.