Zum Inhalt springen

Match in Rust

match vergleicht einen Wert mit einer Liste von Mustern (Patterns) und führt den Code des Musters aus, das passt. Wenn du schon mal eine switch-Anweisung benutzt hast: match ist eine deutlich mächtigere Version davon. Und wenn nicht, ist es trotzdem eines der nützlichsten Werkzeuge, die du früh lernen kannst.

fn main() {
let day = 3;
match day {
1 => println!("Montag"),
2 => println!("Dienstag"),
3 => println!("Mittwoch"),
4 => println!("Donnerstag"),
5 => println!("Freitag"),
_ => println!("Wochenende"),
}
}

Ausgabe:

Mittwoch
▶ Selbst ausprobieren

Jede Zeile der Form Muster => Code heißt Arm (Zweig). Der _ ist ein Catch-all (Auffangmuster): Er passt auf alles, was weiter oben nicht aufgeführt ist. match verlangt, dass jeder mögliche Wert behandelt wird. Deshalb steht _ meistens am Ende und deckt „alles andere“ ab.

Mit | fasst du mehrere Werte in einem Arm zusammen:

fn main() {
let day = 6;
match day {
1 | 2 | 3 | 4 | 5 => println!("Werktag"),
6 | 7 => println!("Wochenende"),
_ => println!("Kein gültiger Tag"),
}
}
▶ Selbst ausprobieren

Bei Zahlen kannst du mit ..= einen ganzen Bereich abgleichen:

fn main() {
let score = 85;
match score {
90..=100 => println!("A"),
75..=89 => println!("B"),
60..=74 => println!("C"),
_ => println!("F"),
}
}
▶ Selbst ausprobieren

Genau wie if kann auch match einen Wert liefern:

fn main() {
let day = 6;
let kind = match day {
1 | 2 | 3 | 4 | 5 => "Werktag",
6 | 7 => "Wochenende",
_ => "unbekannt",
};
println!("{kind}");
}
▶ Selbst ausprobieren

match ist nicht nur für Zahlen da. Es funktioniert auch mit String-Slices (&str) und mit Zeichen. Zeichenbereiche wie 'a'..='z' funktionieren genau wie Zahlenbereiche:

fn main() {
let command = "stop";
match command {
"start" => println!("Starte ..."),
"stop" | "quit" => println!("Halte an."),
_ => println!("Unbekannter Befehl: {command}"),
}
let letter = 'k';
let kind = match letter {
'a' | 'e' | 'i' | 'o' | 'u' => "ein Vokal",
'a'..='z' => "ein Konsonant",
'0'..='9' => "eine Ziffer",
_ => "etwas anderes",
};
println!("'{letter}' ist {kind}");
let name = String::from("Ferris");
match name.as_str() {
"Ferris" => println!("Hallo, Krabbe!"),
_ => println!("Hallo, {name}!"),
}
}

Ausgabe:

Halte an.
'k' ist ein Konsonant
Hallo, Krabbe!
▶ Selbst ausprobieren

Zwei Dinge fallen hier auf:

  • Die Reihenfolge zählt. 'a' liegt auch in 'a'..='z', aber der Vokal-Arm kommt zuerst. Vokale erreichen den Konsonanten-Arm also nie. Rust nimmt immer den ersten Arm, der passt.
  • Ein String braucht .as_str(). Text in Anführungszeichen wie "Ferris" ist ein &str. Wenn du einen String direkt damit abgleichst, bricht Rust mit error[E0308]: mismatched types ... expected String, found &str ab – die Typen passen nicht zusammen. .as_str() liefert dir eine &str-Ansicht des String, mit der die Muster vergleichen können. (Den Unterschied zwischen beiden erklärt die Seite Strings.)

Der Abgleich unterscheidet Groß- und Kleinschreibung: "Stop" passt nicht auf "stop". Kommt der Text von einem Benutzer, ist ein üblicher Trick, auf input.to_lowercase().as_str() abzugleichen.

Für einfache Ja/Nein-Prüfungen funktioniert beides. Sobald du aber mehr als zwei oder drei Möglichkeiten hast, ist match im Vorteil: Es liest sich besser als eine lange Kette aus else if, und der Compiler prüft, ob du jeden Fall abgedeckt hast. Für eine einzelne Ja/Nein-Bedingung bleibt if/else das richtige Werkzeug.

Speichere eine Monatszahl month (2). Berechne mit match als Ausdruck, wie viele Tage der Monat hat (Schaltjahre ignorierst du), und gib Monat 2 hat 28 Tage aus. Tipp: Die Monate 1, 3, 5, 7, 8, 10 und 12 haben 31 Tage. Fasse sie mit | in einem Arm zusammen.

Lösung anzeigen
fn main() {
let month = 2;
let days = match month {
1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
4 | 6 | 9 | 11 => 30,
2 => 28,
_ => 0, // kein echter Monat
};
println!("Monat {month} hat {days} Tage");
}

Ausgabe:

Monat 2 hat 28 Tage
▶ Selbst ausprobieren

Webserver antworten mit einer Zahl. Mach aus einem code eine kurze Bedeutung: 200 ist "OK", 404 ist "Not Found", jeder andere Code von 400 bis 499 ist "Client-Fehler", 500 bis 599 ist "Server-Fehler", und alles andere ist "Unbekannt". Probier es mit 503 aus. Tipp: Setz den genauen 404-Arm über den Bereich 400..=499, sonst wird er nie erreicht.

Lösung anzeigen
fn main() {
let code = 503;
let meaning = match code {
200 => "OK",
404 => "Not Found", // muss vor dem Bereich 400..=499 stehen
400..=499 => "Client-Fehler",
500..=599 => "Server-Fehler",
_ => "Unbekannt",
};
println!("{code}: {meaning}");
}

Ausgabe:

503: Server-Fehler
▶ Selbst ausprobieren
  • match vergleicht einen Wert mit Mustern und führt den passenden Arm aus.
  • Jeder mögliche Wert muss behandelt werden – nimm _ als Catch-all.
  • Mit | kombinierst du Werte, mit ..= gleichst du einen Bereich ab.
  • Auch &str-Text und char-Werte lassen sich abgleichen; für einen String nimmst du .as_str().
  • Wie if kannst du match als Ausdruck verwenden, der einen Wert liefert.

Kurzer Check

1. Was bewirkt das Muster _ in einem match-Ausdruck?

2. Was passiert, wenn ein match-Ausdruck nicht jeden möglichen Wert behandelt und keinen _-Arm hat?

3. Wie gleichst du mehrere Werte wie 1, 2 oder 3 in einem einzigen Arm ab?

Punkte: 0 / 3