Enums und Pattern Matching sind das Rückgrat sicherer Rust-APIs. Wo C-artige Sprachen ein Enum oft als „nummerierte Konstanten" verstehen, ist ein Rust-Enum ein vollständiger algebraischer Datentyp: jede Variante kann eigene Daten mitbringen. Option<T> ersetzt null, Result<T, E> ersetzt Exceptions, eigene Enums modellieren State-Machines und Domain-Logik. Dazu kommt match mit erschöpfender Prüfung — der Compiler verlangt, dass du jede Variante behandelst. Wer das ernst nimmt, schreibt Programme, in denen ganze Klassen von Bugs schlichtweg unmöglich sind. Dieses Kapitel führt durch Enums, Pattern Matching in voller Breite, die zwei wichtigsten Stdlib-Enums und die kompakten Formen if let, while let, let else.
Was ein Rust-Enum kann
In Sprachen wie C ist ein Enum oft nur eine Sammlung benannter Integer:
enum HttpMethod {
GET,
POST,
PUT,
DELETE
};Ein Rust-Enum kann das auch — aber viel mehr:
enum Message {
Text(String), // Tuple-Variante
Click { x: i32, y: i32 }, // Struct-Variante
Ping, // Unit-Variante
Custom { typ: String, payload: Vec<u8> },
}Jede Variante kann eigene Daten haben, in unterschiedlicher Form. Das macht Enums in Rust zu einem mächtigen Werkzeug für Sum-Types (oder „algebraische Datentypen") — eine Werte-Sammlung, in der zur Laufzeit genau eine Variante aktiv ist.
Match — der exhaustive Pattern-Matcher
Der natürliche Begleiter eines Enums ist match:
# enum Message { Text(String), Click { x: i32, y: i32 }, Ping, Custom { typ: String, payload: Vec<u8> } }
fn behandle(m: &Message) {
match m {
Message::Text(s) => println!("Text: {s}"),
Message::Click { x, y } => println!("Klick bei ({x}, {y})"),
Message::Ping => println!("Ping"),
Message::Custom { typ, payload } =>
println!("Custom {typ} mit {} Bytes", payload.len()),
}
}Der wichtigste Aspekt: match ist exhaustive — du musst alle Varianten behandeln. Wenn du eine vergisst, ist das Compile-Fehler. Wenn das Enum später um eine neue Variante erweitert wird, weist dich der Compiler überall darauf hin. Eine ganze Bug-Klasse („vergessen, die neue Variante zu handhaben") ist eliminiert.
Was dich erwartet
- Enum-Grundlagen — Syntax, drei Varianten-Typen (Unit/Tuple/Struct), methoden via impl, Memory-Layout mit Niche-Optimization, Diskriminanten.
- Option<T> — der Ersatz für
null.Some(T)oderNone. Methoden wieunwrap,unwrap_or,map,and_then,?-Operator. Wann was, häufige Patterns. - Result<T, E> — der Ersatz für Exceptions.
Ok(T)oderErr(E). Der zentrale?-Operator, Error-Conversion mitFrom-Impl, Patterns für Library-vs-Application-Errors. - match-Exhaustiveness — wie der Compiler die Vollständigkeit prüft, Wildcard
_, der#[non_exhaustive]-Spezialfall, und die häufigsten match-Stolperfallen. - Patterns-Katalog — Pattern-Matching in voller Breite: Literal-Patterns, Range-Patterns, Struct-/Tuple-/Slice-Patterns,
ref-Bindings,@-Bindings, Guards mitif, Or-Patterns. - if let und while let — Pattern-Match für genau eine Variante. Kompakter als
matchbei einzelnen Branches. - let else — Pattern-Match mit garantiertem divergenten Else-Branch. Idiomatisches Early-Return-Pattern seit Rust 1.65.
Was du nach diesem Kapitel kannst
- Eigene Enums mit allen drei Varianten-Formen designen — Unit, Tuple, Struct.
Option<T>undResult<T, E>souverän nutzen — mit?,unwrap_or_else,map,and_then.match-Statements schreiben, die exhaustive sind und sicher mit neuen Varianten umgehen.- Alle Pattern-Formen einsetzen: Literale, Ranges, Struct-Destrukturierung, Slice-Patterns,
ref-Bindings,@-Bindings, Guards, Or-Patterns. if let,while let,let elseals kompakte Alternative zumatcheinsetzen.- Domain-Logik als Sum-Types modellieren — State-Machines, Befehle, Events.
Im nächsten Kapitel geht es zu Collections — Vec, String, HashMap und Co. — die wichtigsten Stdlib-Container.
Weiterführende Ressourcen
Externe Quellen
- The Rust Book – Enums
- The Rust Book – Patterns and Matching
- Rust Reference – Enumerations
- Rust Reference – Patterns