Wie man Option<String> in Option<&str> in Rust ohne Schmerz umwandelt

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

Warum sind Sie hier? Seien Sie ehrlich

\n\n

Sie programmieren in Rust und stoßen plötzlich auf eine Wand. Sie haben ein Option<String> – einen Wert, der vorhanden sein kann oder auch nicht. Aber die Funktion, die Sie aufrufen möchten, erwartet Option<&str>. Und der Compiler blickt Sie vorwurfsvoll an und gibt einen Fehler aus, bei dem Sie am liebsten den Laptop zuklappen und Tee trinken gehen würden.

\n\n

Keine Sorge. Diese Situation tritt so häufig auf, dass die Frage "Converting from Option<String> to Option<&str>" auf Stack Overflow tausende Aufrufe gesammelt hat. Sie sind nicht allein.

\n\n

In diesem Artikel werden wir verstehen, warum diese Konvertierung so viele Fragen aufwirft, und – am wichtigsten – wie man sie richtig durchführt. Ohne Magie, ohne unnötiges Kopieren im Speicher, mit vollständigem Verständnis dessen, was unter der Haube passiert.

\n\n

Das Problem: Warum kann man nicht einfach konvertieren?

\n\n

Zunächst ein kurzer Blick auf die Typen.

\n\n
    \n
  • String ist ein besitzender Typ. Er besitzt die Daten auf dem Heap und ist für deren Freigabe verantwortlich.
  • \n
  • &str ist ein Verweis auf einen String-Slice. Er leiht sich die Daten aus, ohne sie zu besitzen.
  • \n
\n\n

Und hier beginnt der Spaß. Option<String> ist ein möglicherweise vorhandener String, den Sie besitzen. Option<&str> ist ein möglicherweise vorhandener Verweis auf einen String.

\n\n

Das Problem ist, dass Sie nicht einfach einen Verweis auf den Wert innerhalb des Option nehmen und nach außen geben können, wenn das Option temporär ist. Der Verweis muss auf etwas zeigen, und dieses "Etwas" muss lange genug leben.

\n\n

Schauen wir uns einen typischen Anfängerfehler an:

\n\n
fn process(value: Option<String>) {\n    // Fehler! cannot return reference to temporary value\n    let ref_value: Option<&str> = value.as_ref().map(|s| s.as_str());\n    // oder noch direkter:\n    let ref_value: Option<&str> = Some(value.unwrap().as_str()); // BUMM!\n}
\n\n

Der Compiler explodiert in Rot. Warum? Weil value der Besitzer des Strings ist. Wenn Sie versuchen, einen &str davon zu nehmen, darf der Verweis nicht länger leben als value selbst. Und wenn value ein temporäres Objekt ist (z. B. das Ergebnis eines Funktionsaufrufs), wird der Verweis zu einem hängenden Verweis (dangling reference).

\n\n

Lösung Nr. 1: as_deref() – Ihr neuer bester Freund

\n\n

Der eleganteste Weg, Option<String> in Option<&str> zu konvertieren, ist die Methode as_deref().

\n\n

Wie funktioniert das? as_deref() macht zwei Dinge:

\n
    \n
  1. Es nimmt &Option<T> und wandelt es in Option<&T> um (das macht as_ref()).
  2. \n
  3. Dann wendet es Deref auf den inneren Wert an und wandelt &String in &str um.
  4. \n
\n\n

So sieht das im Code aus:

\n\n
fn main() {\n    let my_string: Option<String> = Some(String::from("Hallo, Rust!"));\n    \n    // Magie in einer Zeile:\n    let my_str_ref: Option<&str> = my_string.as_deref();\n    \n    match my_str_ref {\n        Some(s) => println!("String: {}", s),\n        None => println!("Kein String vorhanden"),\n    }\n    // my_string lebt und ist wohlauf!\n    println!("Ursprünglicher String: {:?}", my_string);\n}
\n\n

Beachten Sie: my_string bleibt der Besitzer der Daten. Wir haben nur einen Verweis auf seinen Inhalt genommen. Das bedeutet, dass my_str_ref nur so lange lebt, wie my_string lebt.

\n\n

Was ist, wenn Option leer ist?

\n

Ganz einfach:

\n\n
fn main() {\n    let empty: Option<String> = None;\n    let result: Option<&str> = empty.as_deref();\n    println!("{:?}", result); // None\n}
\n\n

Keine Paniken, keine Abstürze. Funktioniert wie ein Uhrwerk.

Blogs

Buchempfehlungen