Einleitung: Warum kann man in Rust nicht einfach Strings addieren?
\n\nWenn Sie von Python oder JavaScript zu Rust gewechselt sind, wird Sie wahrscheinlich als Erstes der Versuch schockieren, "Hello, " + "world!" zu schreiben. Der Compiler begrüßt Sie mit einer roten Wellenlinie und einer rätselhaften Fehlermeldung. In der Welt von Python würde das sofort funktionieren, aber Rust ist ein anderes Biest. Die Frage "How do I concatenate strings?" hat auf Stack Overflow Hunderttausende von Aufrufen, und das nicht ohne Grund.
Das Problem ist, dass die String-Konkatenation in Rust nicht nur syntaktischer Zucker ist. Es geht um Speicherverwaltung, Ownership (Besitz) und Datentypen. Wenn Sie Anfänger sind, können Sie leicht auf klassische Fallstricke treten: den Besitz eines Strings verlieren, versehentlich Gigabyte an Daten kopieren oder sich einfach in String und &str verheddern.
In diesem Artikel analysieren wir die 5 häufigsten Fehler, die Anfänger beim Zusammenfügen von Strings in Rust machen, und zeigen, wie man sie vermeidet. Sie erfahren, wann Sie +, wann format! und wann push_str verwenden sollten. Los geht's!
Fehler Nr. 1: Den Besitz (Ownership) vergessen
\n\nWie es aussieht
\n\nStellen Sie sich vor, Sie schreiben Code:
\n\nlet s1 = String::from("Hallo");\nlet s2 = String::from(", Welt!");\nlet s3 = s1 + &s2; // Fehler? Oder nicht?\nprintln!("{}", s1); // Kompilierungsfehler!\n\nSie erwarten, dass s1 weiterhin verfügbar ist, aber der Compiler sagt: "Nein, s1 wurde verschoben (moved)".
Was ist der Kern des Fehlers
\n\nIn Rust verwendet der Operator + für Strings die Signatur fn add(self, s: &str) -> String. Beachten Sie das self – das bedeutet, dass der erste String konsumiert (consumes) wird und Sie ihn nicht mehr verwenden können. Sie "geben" s1 buchstäblich an die Funktion add weiter, und sie wird unzugänglich.
Wie man es behebt
\n\nEs gibt zwei Wege:
\n\n- \n
- Den String klonen (falls Sie den Original benötigen):
let s3 = s1.clone() + &s2;\n - Die Reihenfolge ändern oder
format!verwenden: \n
let s1 = String::from("Hallo");\nlet s2 = String::from(", Welt!");\nlet s3 = format!("{}{}", s1, s2); // s1 und s2 bleiben verfügbar\nprintln!("{}", s1); // Funktioniert!\n\nTipp: Wenn Sie s1 nach der Konkatenation nicht mehr verwenden möchten, verwenden Sie ruhig +. Das ist schneller als format!, da kein neuer Puffer von Grund auf erstellt wird.
Fehler Nr. 2: Verwechslung von String und &str
\n\nWie es aussieht
\n\nSie versuchen, einen String mit einem Literal zu addieren:
let s = String::from("Hello");\nlet result = s + " world"; // Funktioniert!\n\nAber wenn Sie es umgekehrt versuchen:
\n\nlet s = "Hello";\nlet result = s + String::from(" world"); // Fehler!\n\nWas ist der Kern des Fehlers
\n\nDer Operator + funktioniert nur, wenn die linke Seite ein String und die rechte Seite ein &str ist. Das Literal " world" ist automatisch ein &str, daher funktioniert das erste Beispiel. Im zweiten Beispiel ist s ein &str, das keine add-Methode hat.
Wie man es behebt
\n\nWandeln Sie &str in String um oder verwenden Sie format!:
let s = "Hello";\nlet result = format!("{} {}", s, "world"); // Universelle Methode\n// Oder\nlet result = s.to_string() + " world"; // to_string() erstellt einen String\n\nGoldene Regel: String ist ein besitzender Typ (owned), &str ist eine Ausleihe (borrow). Die Konkatenation erfordert immer den Besitz auf der linken Seite.