ProgrammierungRust Entwickler

Wie funktionieren Pattern Matching und Destructuring in Rust und welche Feinheiten sind bei ihrer Verwendung zu beachten?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

Pattern Matching in Rust ermöglicht es, Werte gemäß ihrer Struktur zu zerlegen, komplexe Typen mit den Konstruktionen match, if let, while let zu analysieren und zu verarbeiten. Destrukturierung ist nützlich für die Arbeit mit Tupeln, Strukturen, Enums und sogar Referenzen.

Beispiel mit Enum:

enum Message { Quit, ChangeColor(i32, i32, i32), Write(String), } let m = Message::ChangeColor(255, 0, 0); match m { Message::Quit => println!("Quit!"), Message::ChangeColor(r, g, b) => println!("Farbe: {} {} {}", r, g, b), Message::Write(text) => println!("Text: {}", text), }

Destrukturierung von Strukturen:

struct Point { x: i32, y: i32 } let p = Point { x: 10, y: 20 }; let Point { x, y } = p;

Feinheiten:

  • Die Verwendung von ref und ref mut ermöglicht es, Referenzen beim Zerlegen zu erhalten.
  • Mit @ kann man einen Teil des Musters "umbenennen".
  • Matching nach Werten, Bereichen, Bedingungen (if guard).
  • Bei der Destrukturierung von Referenzen (&SomeType) ist es wichtig, an Besitz und Borrowing zu denken.

Fangfrage

Kann man immer "_" (Unterstrich) verwenden, um Teile des Musters zu ignorieren und Compilerwarnungen zu vermeiden?

Nicht immer. Der Unterstrich überspringt zwar den Wert, aber wenn man nicht alle Varianten eines Enums verarbeitet und "_" für catch-all verwendet, kann man die Behandlung neuer Varianten beim Erweitern des Enums in der Zukunft verpassen. Es ist besser, immer explizit die wichtigen Varianten aufzulisten, damit der Compiler auf nicht berücksichtigte Fälle hinweist!

match result { Ok(val) => ..., Err(err) => ..., //_ => ... // nicht empfohlen für Enums! }

Beispiele realer Fehler aufgrund des Nichtwissens über die Feinheiten des Themas


Geschichte

In einer IoT-Anwendung hörte das Gerät auf zu antworten, weil beim Hinzufügen einer neuen Variante zum Enum an der Stelle des Pattern Matchings ein catch-all "_" verwendet wurde. Der Fehler blieb bis zur Bereitstellung unsichtbar. Danach wurden kritische Enums immer nur durch explizites Auflisten der Varianten verarbeitet.


Geschichte

Für eine komplexe Struktur mit verschachtelten Tupeln wurde vergessen, die Syntax zur Destrukturierung rekursiver Felder hinzuzufügen, und anstelle von Referenzen wurden große Objekte versehentlich kopiert, was zu Leistungsproblemen führte.


Geschichte

In einem funktionalen Nachrichtenübertragungsteil zwischen Threads wurde die Destrukturierung mit if-let verwendet, aber seltene Varianten des Enums wurden ignoriert. Mit dem Auftreten neuer Geschäftslogik gingen Nachrichten einfach verloren. Danach wurde im Teamstil eine Regel festgelegt — jedes match-Ausdruck muss erschöpfend ohne catch-all sein.