Comment réussir un entretien Rust : les questions essentielles
Rust est l'un des langages de programmation les plus demandés en 2025. Il combine les performances du C/C++ avec la sécurité mémoire, ce qui en fait un choix idéal pour la programmation système, le web assembly et les projets blockchain. Cependant, l'entretien Rust effraie souvent les candidats en raison de son système strict de possession, d'emprunt et de durée de vie. Dans cet article, nous analysons le top 10 des questions qui vous seront posées et vous montrons les bonnes réponses avec des exemples de code.
1. Qu'est-ce que la possession (ownership) et comment fonctionne-t-elle ?
La possession est le fondement de Rust. Chaque valeur dans Rust a exactement un propriétaire. Lorsque le propriétaire sort de la portée, la valeur est automatiquement supprimée.
fn main() { let s = String::from("hello"); // s est le propriétaire de la chaîne let t = s; // la possession est déplacée vers t // println!("{}", s); // ERREUR : s ne possède plus la valeur println!("{}", t); // OK}Ce qui est demandé en entretien : expliquez la différence entre le déplacement (move) et la copie (copy). Les types qui implémentent le trait Copy (par exemple, i32, bool) sont copiés, et non déplacés.
2. Comment fonctionne l'emprunt (borrowing) ?
L'emprunt permet d'utiliser temporairement une valeur sans transférer la possession. Il existe deux types d'emprunt : immuable (&T) et mutable (&mut T).
fn main() { let mut s = String::from("hello"); let r1 = &s; // emprunt immuable let r2 = &s; // plusieurs emprunts immuables possibles // let r3 = &mut s; // ERREUR : impossible d'avoir un emprunt mutable et immuable simultanément println!("{} {}", r1, r2); let r3 = &mut s; // OK : après que r1 et r2 sont sortis de la portée r3.push_str(" world"); println!("{}", r3);}Règle clé : à tout moment, il peut y avoir soit un seul emprunt mutable, soit un nombre illimité d'emprunts immuables.
3. Qu'est-ce que la durée de vie (lifetimes) ?
Les durées de vie sont des annotations dont le compilateur Rust a besoin pour vérifier que les références ne deviennent pas pendantes. Elles sont le plus souvent utilisées dans les fonctions qui retournent des références.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y }}
fn main() { let s1 = String::from("longue"); let s2 = "courte"; let result = longest(&s1, s2); println!("La chaîne la plus longue : {}", result);}Astuce : dans la plupart des cas, le compilateur déduit lui-même la durée de vie (élision). Les annotations ne sont nécessaires que pour les cas complexes.
4. Que sont les traits et comment les utiliser ?
Les traits sont l'équivalent des interfaces dans d'autres langages. Ils définissent un comportement commun pour différents types.
trait Summary { fn summarize(&self) -> String;}
struct Article { title: String, content: String,}
impl Summary for Article { fn summarize(&self) -> String { format!("{} : {}...", self.title, &self.content[..20]) }}
fn main() { let article = Article { title: String::from("Rust"), content: String::from("Rust est un langage sûr et rapide"), }; println!("{}", article.summarize());}Important : les traits peuvent avoir des implémentations par défaut et peuvent être paramétrés (traits génériques).
5. Quelle est la différence entre String et &str ?
C'est l'une des questions les plus fréquentes. String est une chaîne mutable, possédée, stockée sur le tas. &str est un emprunt immuable d'une tranche de chaîne, qui peut référencer une String, un littéral de chaîne ou une partie d'une chaîne.
fn main() { let s1 = String::from("hello"); // String let s2: &st