Einleitung: Warum ist Rust in Vorstellungsgesprächen so anspruchsvoll?
Rust ist eine systemsorientierte Programmiersprache, die für ihre Speichersicherheit und hohe Leistung bekannt ist. Der Rust-Compiler ist streng, aber fair: Er erlaubt keinen Ownership-Fehler oder eine hängende Referenz. Deshalb wird in Rust-Vorstellungsgesprächen selten Syntax "nach Lehrbuch" abgefragt. Stattdessen testen Interviewer ein tiefes Verständnis des Speichermodells, der Ressourcenverwaltung und des idiomatischen Codes.
In diesem Artikel werden wir die Top 10 Fragen aufschlüsseln, die am häufigsten in Vorstellungsgesprächen für Junior- und Middle-Rust-Entwickler gestellt werden. Jede Frage enthält eine Erklärung und ein Codebeispiel. Wenn Sie sich auf ein Vorstellungsgespräch vorbereiten, wird dieser Artikel Ihre Checkliste sein.
1. Ownership und Borrowing
Dies ist die Grundlage von Rust. Ohne das Verständnis von Ownership werden Sie das Vorstellungsgespräch nicht bestehen. Ein Interviewer könnte Sie bitten, den Unterschied zwischen String und &str zu erklären oder zu fragen, warum ein bestimmter Code nicht kompiliert.
Frage: Erklären Sie, was Ownership ist und wie Datenübergabe in Funktionen funktioniert.
Antwort: In Rust hat jeder Wert genau einen Besitzer (Owner). Wenn eine Variable den Gültigkeitsbereich verlässt, wird der Wert freigegeben. Das Übergeben eines Wertes an eine Funktion bedeutet einen Besitzerwechsel (Move), es sei denn, der Typ implementiert das Copy-Trait.
fn main() { let s1 = String::from("hallo"); let s2 = s1; // s1 wird zu s2 bewegt // println!("{}", s1); // Fehler! s1 besitzt den String nicht mehr println!("{}", s2);}Wenn Sie Daten übergeben möchten, ohne den Besitzer zu verlieren, verwenden Sie Referenzen (&):
fn main() { let s1 = String::from("hallo"); let len = calculate_length(&s1); // Ausleihen (Borrowing) println!("Die Länge von '{}' ist {}.", s1, len);}
fn calculate_length(s: &String) -> usize { s.len()}Frage: Was ist mutable Borrowing und warum kann es nur eines geben?
Antwort: Mutable Borrowing (&mut) erlaubt es Ihnen, einen Wert über eine Referenz zu ändern. Der Compiler garantiert, dass es nur eine mutable Referenz im Gültigkeitsbereich gibt, um Datenrennen zu verhindern.
fn main() { let mut s = String::from("hallo"); let r1 = &mut s; // let r2 = &mut s; // Fehler! Kann nicht zwei mutable Referenzen haben r1.push_str(", Welt"); println!("{}", r1);}2. Lifetimes
Lifetimes sind das, was Anfänger abschreckt. In einem Vorstellungsgespräch werden Sie gebeten zu erklären, warum 'a-Annotationen benötigt werden und wie der Compiler Lifetimes ableitet.
Frage: Wann müssen Sie Lifetimes explizit angeben?
Antwort: Wenn eine Funktion eine Referenz zurückgibt und der Compiler nicht selbstständig bestimmen kann, wie lange diese leben wird. Ein klassisches Beispiel ist eine Funktion, die den längeren von zwei Strings zurückgibt:
fn laengste<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y }}
fn main() { let string1 = String::from("langer String"); let result; { let string2 = String::from("kurz"); result = laengste(&string1, &string2); } // println!("{}", result); // Fehler! string2 wurde freigegeben, Referenz hängt}Die Annotation 'a besagt: "Die Lebensdauer der zurückgegebenen Referenz ist gleich der kürzeren Lebensdauer der Eingabereferenzen."
Frage: Was ist Elision (Lifetime-Elision-Regeln)?
Antwort: Der Compiler fügt in einfachen Fällen automatisch Lifetimes ein. Wenn eine Funktion eine Referenz nimmt und eine Referenz zurückgibt, wird die Lifetime abgeleitet. Wenn es mehrere Eingabereferenzen gibt, müssen Sie diese explizit angeben.
3. Enum, Pattern Matching und Option/Result
Rust macht umfangreichen Gebrauch von algebraischen Typen.