Introduction : Pourquoi Rust est un défi pour l'intervieweur
\nRust est un langage qui exige du développeur une compréhension approfondie de la gestion de la mémoire, du système de types et du modèle de concurrence. Un entretien Rust n'est pas une vérification de la syntaxe, mais un test de compréhension de la philosophie du langage. Dans cet article, nous analyserons les questions clés qui peuvent vous être posées lors d'un entretien — des bases de la possession aux sujets avancés comme l'asynchrone. Vous découvrirez quelles réponses l'intervieweur attend et comment éviter les erreurs typiques.
\n\n1. Possession, emprunt et durée de vie
\n1.1. Qu'est-ce que la possession (ownership) et comment fonctionne-t-elle ?
\nC'est le fondement de Rust. Chaque valeur a exactement un propriétaire. Lorsque le propriétaire sort de la portée, la valeur est supprimée. Cela permet d'éviter le ramasse-miettes et garantit la sécurité de la mémoire à la compilation.
\nfn main() {\n let s1 = String::from("bonjour");\n let s2 = s1; // s1 est déplacé dans s2\n // println!("{}", s1); // Erreur ! s1 n'est plus valide\n println!("{}", s2); // Fonctionne\n}\nConseil : Expliquez la différence entre le déplacement (move) et la copie (copy). Pour les types qui implémentent le trait Copy (par exemple, les entiers), il n'y a pas de déplacement — les données sont copiées.
1.2. Règles de l'emprunt (borrowing)
\nL'emprunt permet d'utiliser une référence à des données sans transférer la propriété. Il existe deux types de références :
\n- \n
- Immuables (&T) : il peut y en avoir autant que l'on veut, les données ne peuvent pas être modifiées. \n
- Mutables (&mut T) : une seule référence aux données dans la portée actuelle. \n
fn main() {\n let mut s = String::from("hello");\n let r1 = &s; // référence immuable\n let r2 = &s; // une autre référence immuable — ok\n // let r3 = &mut s; // Erreur ! Impossible d'avoir des références immuables et mutables simultanément\n println!("{} {}", r1, r2);\n}\nQuestion piège : "Pourquoi Rust interdit-il les références mutables et immuables simultanément ?" Réponse : pour empêcher les courses de données (data races) à la compilation.
\n\n1.3. Durée de vie (lifetimes) — comment l'expliquer simplement
\nLa durée de vie est une annotation qui indique au compilateur combien de temps les références seront valides. Le plus souvent, le compilateur les déduit lui-même, mais dans les fonctions complexes, il faut les spécifier explicitement.
\nfn longest<'a>(x: &'a str, y: &'a str) -> &'a str {\n if x.len() > y.len() { x } else { y }\n}\nIdée clé : 'a signifie que la référence retournée ne vivra pas plus longtemps que les deux références d'entrée. Cela garantit que la référence ne deviendra pas pendante (dangling).
2. Énumérations, filtrage par motif et traits
\n2.1. Enum en Rust — pourquoi c'est plus puissant que dans d'autres langages
\nEn Rust, les énumérations peuvent stocker des données de n'importe quel type — chaînes, nombres, structures et même d'autres énumérations. Cela permet de créer des types de données algébriques (ADT).
\nenum Message {\n Quit,\n Move { x: i32, y: i32 },\n Write(String),\n ChangeColor(i32, i32, i32),\n}\nQuestion typique : "Comment fonctionne Option<T> et pourquoi Rust n'a-t-il pas de null ?" Réponse : Option est une enum qui peut être Some(T) ou None. Le compilateur oblige à traiter les deux cas, ce qui élimine les erreurs de pointeur nul.
2.2. Filtrage par motif (pattern matching)
\nLa construction match est le cœur de Rust. Elle doit être exhaustive.
fn describe_point(point: (i32, i32)) -> &'static str {\n match point {\n (0, 0) => "origine",\n (0, _) => "sur l'axe X",\n (_, 0) => "sur l'axe Y",\n _ => "quelque part dans le plan",\n }\n}\nAstuce pour l'entretien : Utilisez if let pour