Tutoriel Rust : Sécurité mémoire et concurrence

Dernière mise à jour: 04/12/2025
Auteur: Isaac
  • Rust garantit la sécurité de la mémoire lors de la compilation grâce à la gestion de la propriété, des emprunts et des durées de vie, sans utiliser de ramasse-miettes.
  • Le système de types et les règles d'alias permettent la concurrence sans conflits d'accès aux données grâce à l'utilisation de mutex, de canaux et de pointeurs intelligents.
  • Cargo, crates.io et un écosystème actif simplifient la gestion des dépendances, la compilation, les tests et le déploiement.
  • La compréhension des structures, des énumérations, des options et des résultats est essentielle pour gérer les erreurs et modéliser des données sécurisées dans les applications concurrentes.

Langage de programmation C vs Rust : avantages et inconvénients

Rust est devenu l'un de ces langages qui Tous les développeurs de systèmes finissent par l'entendre encore et encore.Il est aussi rapide que le C et le C++, mais avec une attention quasi obsessionnelle portée à la sécurité de la mémoire et à une gestion efficace de la concurrence. Il ne s'agit pas d'un simple argument marketing : sa conception repose sur la détection des erreurs par le compilateur dès la compilation – des erreurs qui, dans d'autres langages, ne sont visibles qu'une fois le système en production… ou lors d'un plantage.

Si vous souhaitez comprendre Comment Rust assure une gestion sécurisée de la mémoire sans ramasse-miettes et une concurrence sans risque d'erreurs de traitement des donnéesCe tutoriel est fait pour vous. Nous aborderons tous les aspects, des fondamentaux du langage et de son écosystème aux concepts clés tels que la propriété, l'emprunt, les types composés, les outils comme Cargo, et même les types atomiques et le verrouillage, présentés de manière plus accessible pour les débutants en programmation concurrente, le tout en mettant l'accent sur la sécurité et les performances.

Tutoriel Rust : Performances, sécurité mémoire et concurrence

Rust est un langage de programmation programmation polyvalent et multi-paradigme, conçu pour programmation système de bas niveau ainsi que pour des projets de haut niveauDepuis OSDes moteurs de jeux et navigateurs aux services web haute performance, cette approche a vu le jour chez Mozilla dans le but d'améliorer la sécurité des logiciels, notamment celle des composants sensibles comme le moteur d'un navigateur.

Sa caractéristique principale est que garantit la sécurité de la mémoire lors de la compilation Rust utilise un système de gestion de la propriété et un vérificateur d'emprunts qui suit la durée de vie de chaque valeur et de ses références, sans recourir à un ramasse-miettes. Ceci permet d'éviter les problèmes classiques tels que les pointeurs non initialisés, les dépassements de tampon ou les fuites de mémoire, sans nécessiter de comptage automatique des références ni de ramasse-miettes.

De plus, Rust est conçu pour faciliter les choses. présence en toute sécuritéSon modèle de typage et de gestion des accès empêche les conflits d'accès aux données entre les threads, du moins dans un code Rust sécurisé. Ainsi, de nombreuses situations dangereuses sont détectées à la compilation, avant même l'exécution de la moindre ligne de code.

Pour toutes ces raisons, les grandes entreprises comme Dropbox, Microsoft, Amazon ou Google Ils ont adopté Rust pour des éléments critiques de leur infrastructure. Et ce n'est pas un hasard s'il figure depuis des années en tête des sondages Stack Overflow comme l'un des langages les plus appréciés des développeurs : il combine les performances du C++ avec un ensemble d'outils modernes (Cargo, crates.io) et une communauté très active, les Rustacés.

Concepts de base : langage de programmation, types et mémoire

Avant d'aborder les spécificités de la sécurité de la mémoire et de la concurrence, il convient de clarifier certains concepts généraux qui apparaissent tout au long de l'ouvrage. le temps Lorsque vous travaillez avec Rust, surtout si vous venez d'autres langues ou si vous débutez tout juste en programmation.

Un langage de programmation est, en fin de compte, un ensemble de règles et de structures qui permet de décrire des algorithmes et les transformer en programmes exécutables. Rust compile en code machine natif grâce à son compilateur. rustcPar conséquent, les performances obtenues sont généralement équivalentes à celles de C et C++.

La gestion de la mémoire est le processus par lequel un programme réserve et libère des blocs de mémoire pendant son exécutionLes erreurs dans ce domaine sont souvent fatales : fuites de mémoire (absence de libération de la mémoire inutilisée), corruption de données due à des écritures hors limites ou utilisation de mémoire après sa libération. Rust y remédie grâce à un système de types très robuste et des règles formelles concernant la propriété, l’emprunt et la durée de vie des ressources.

Rust comporte également des termes comme caractères intelligents et pointeursUn type décrit le type de données stockées par une variable (entiers, nombres à virgule flottante, chaînes de caractères, structures, etc.) et la manière dont elles peuvent être manipulées. Les pointeurs intelligents (par exemple, Box, Rc y Arc) sont des structures qui encapsulent les adresses mémoire et ajoutent une logique supplémentaire pour gérer les ressources en toute sécurité, comme le comptage des références partagées ou le déplacement des valeurs vers le tas.

Dans le domaine de la compétition, des concepts tels que conditions de concurrence, mutex et canaux Ils deviennent indispensables : une condition de concurrence survient lorsque plusieurs threads accèdent et modifient simultanément une ressource partagée sans coordination adéquate ; un mutex (exclusion mutuelle) garantit qu’un seul thread entre dans la section critique à la fois ; et les canaux permettent l’envoi de messages entre les threads sans partage direct de mémoire.

Pourquoi apprendre Rust : Sécurité de la mémoire et concurrence sans crainte

Rust a acquis sa renommée grâce à son offre trois piliers essentiels pour la programmation modernePerformance, sécurité et outils actuels. Voyons pourquoi ces points sont si importants.

En ce qui concerne les performances, Rust compile directement en binaires natifs Sans nécessiter de machine virtuelle ni d'interpréteur, le modèle d'abstractions à coût nul vise à garantir que les abstractions de haut niveau n'entraînent aucune surcharge à l'exécution. Il est donc idéal pour le développement de systèmes. jeux video, des composants de navigateur ou des microservices à faible latence.

La sécurité de la mémoire repose sur son système de propriété et de prêtIl n'y a pas de ramasse-miettes, mais le compilateur sait précisément qui possède chaque ressource, quand elle n'est plus nécessaire et quand elle peut être libérée. Ceci évite les fuites de mémoire, les pointeurs non initialisés et nombre d'erreurs qui ont traditionnellement rendu la programmation en C et C++ si dangereuse.

Dans le domaine de la compétition, Rust poursuit ce qu'on appelle généralement « La concurrence sans crainte »Le système de types lui-même empêche l'existence de racines de données dans du code sécurisé. Si vous souhaitez partager des données mutables entre les threads, vous devrez utiliser des primitives appropriées telles que : Mutex, RwLock o Arcet le compilateur veillera à ce que les règles d'aliasing et de mutabilité soient respectées.

  Comment désinfecter Windows avec Malwarebytes étape par étape

L'expérience de développement est améliorée grâce à des outils modernes tels que CargaisonIl intègre un gestionnaire de paquets et une infrastructure de compilation, ainsi qu'un vaste écosystème de bibliothèques (crates) couvrant tous les aspects, des réseaux asynchrones (Tokyo) aux frameworks web (Actix, Rocket, Axum). Le tout est soutenu par une communauté ouverte, active et très patiente, notamment envers les débutants.

Installation et outils essentiels : rustup, rustc et Cargo

Pour écrire et exécuter vos premiers programmes en Rust, la méthode habituelle consiste à installer la chaîne d'outils officielle à l'aide de rouille (voir le Introduction complète à Rust), un programme d'installation simple et un gestionnaire de versions qui fonctionne sur tous les principaux systèmes d'exploitation.

Avec rouille Vous pouvez installer, mettre à jour et passer d'une version de Rust à l'autre (stable, bêta, nightly) sans problème. Il vous suffit de vous rendre sur la page officielle des outils Rust et de suivre les instructions correspondant à votre système. Une fois installé, le compilateur sera disponible. rustc, le chef de projet cargo et la propre rustup dans votre terminal.

le compilateur rustc C'est ce qui transforme votre code source en binaires exécutables ou en bibliothèques. Bien que vous puissiez l'appeler directement avec commandes como rustc main.rsEn pratique, vous travaillerez presque toujours via Cargo, qui gère les appels à rustc avec les bonnes options.

L'outil central du flux de travail est CargaisonEn quelques commandes seulement, vous pouvez créer de nouveaux projets, gérer les dépendances, compiler, exécuter, tester et publier des packages sur crates.io. Voici quelques commandes de base couramment utilisées : cargo new, cargo build, cargo run, cargo test y cargo check, qui vérifie le code sans produire le fichier exécutable final, idéal pour détecter rapidement les erreurs.

Si vous souhaitez bidouiller sans rien installer, Aire de jeux de rouille (l'exécuteur en ligne officiel) et des plateformes comme Replit vous permettent d'écrire et d'exécuter de petits morceaux de code depuis le navigateur, parfaits pour expérimenter avec des exemples de mémoire et de concurrence sans avoir à configurer l'environnement complet.

Votre premier programme : Bonjour, Rust et flux de base

La manière classique d'entamer une conversation dans n'importe quelle langue est le fameux « Bonjour, monde ». En Rust, un fichier main.rs Le minimum pourrait contenir quelque chose d'aussi simple qu'une fonction main qui affiche une chaîne de caractères à l'écran.

Le mot clé fn indique que nous définissons une fonction, et main Il s'agit du point d'entrée du programme. Le bloc de code de la fonction se place entre les accolades. Pour écrire dans la console, utilisez… macro println!, qui accepte une chaîne littérale (ou un modèle avec des signets) et l'envoie à la sortie standard se terminant par un caractère de nouvelle ligne.

Si vous compilez directement avec rustc main.rs, vous obtiendrez un fichier binaire exécutable (par exemple, main o main.exe (Selon le système). À l'exécution, le message s'affichera dans le terminal. Toutefois, la méthode courante pour travailler avec Rust consiste à laisser Cargo gérer le projet.

Avec cargo new nombre_proyecto Une structure de dossiers est automatiquement créée avec un src/main.rs déjà préparé avec un « Bonjour, monde » et un fichier Cargo.toml qui contient des métadonnées et les dépendances futures. À partir de là, cargo run compiler et exécuter le binaireet il ne recompile que lorsqu'il détecte des modifications.

Cette méthode de travail est non seulement pratique, mais elle vous familiarise dès le départ avec l'écosystème Rust standard, ce qui est très utile lorsque vous commencez à ajouter des crates pour la concurrence, la mise en réseau, les tests ou tout autre besoin.

// Nous déclarons la fonction principale : point d'entrée du programme fn main() { // Nous utilisons la macro println! pour afficher du texte dans la console println!("Bonjour, monde !"); }

Variables, mutabilité et types de données de base

En Rust, les variables sont déclarées avec le mot-clé `var`. letet par défaut sont immuablesAutrement dit, une fois que vous leur avez attribué une valeur, vous ne pouvez plus la modifier à moins de la déclarer explicitement comme mutable avec mut.

L'immuabilité par défaut permet d'éviter des erreurs de logique subtiles, notamment dans les programmes concurrents où plusieurs threads peuvent vouloir modifier la même valeur. Si vous devez la modifier, vous écrivez quelque chose comme let mut contador = 0;À partir de là, vous pouvez réaffecter de nouvelles valeurs à contador.

Rust permet également ce qu'on appelle ombrageVous pouvez déclarer une nouvelle variable portant le même nom dans la même portée, masquant ainsi la précédente. Cela ne revient pas à la modifier, car vous créez une nouvelle valeur (qui peut même être d'un type différent). Par exemple, vous pouvez convertir une chaîne de caractères en un entier en utilisant le même nom, à condition qu'il s'agisse d'une nouvelle déclaration. let.

Le système de types de Rust est statique, ce qui signifie que Le type de chaque variable est connu lors de la compilation.Cependant, l'inférence de type est très puissante : si vous écrivez let x = 5;Le compilateur suppose qu'il s'agit d'un i32 Sauf indication contraire de votre part. Vous pouvez ajouter des notes telles que : let x: i64 = 5; quand vous voulez être explicite.

Parmi les types scalaires disponibles figurent les entiers signés et non signés (i8, u8, i32, etc.), les flottants (f32, f64), les booléens (bool) et les caractères Unicode (char). Ces types simples sont généralement peu coûteux à copier et beaucoup implémentent cette caractéristique Copyce qui signifie que lorsque vous les assignez ou les transmettez à une fonction, ils sont copiés au lieu d'être déplacés.

Chaînes de caractères en Rust : &str et String

La gestion du texte en Rust peut être un peu déroutante au premier abord car elle fait clairement la distinction entre « tranches » de chaînes et chaînes propriétairesLes deux éléments clés sont &str y String.

Un &str est un tranche de chaîne immuableVue d'une séquence d'octets UTF-8 stockée quelque part. Exemples typiques : littéraux comme "Hola"qui sont du type &'static str (Elles existent pendant toute la durée de vie du programme et sont intégrées au fichier binaire.) Les tranches ne possèdent pas les données ; elles ne font que les référencer.

  Comment personnaliser complètement la barre des tâches dans Windows 11 : guide complet et conseils avancés

String, d'autre part, est un chaîne de caractères propre, mutable et hébergée dans le tasIl peut être redimensionné, concaténé, transmis entre fonctions en déplaçant sa propriété, etc. Il est souvent utilisé lorsque l'on souhaite créer du texte dynamique ou le stocker à long terme dans des structures.

Dans de nombreux cas, vous passerez de l'un à l'autre : par exemple, vous créerez un String::from("hola") d'une trancheou vous emprunterez un &str d'un String en passant des références à des fonctions qui n'ont besoin que de lire.

Cette séparation entre les données possédées et les données empruntées est essentielle à la gestion de la mémoire et s'étend au reste du langage : les collections, les structures et les énumérations suivent les mêmes idées de qui possède et de qui ne fait que regarder.

Fonctions, flux de contrôle et commentaires

Les fonctions en Rust sont définies avec fn et permettent d'organiser le programme en unités logiques réutilisables. Chaque fonction spécifie le type de ses paramètres et son type de retour suivre une flèche ->Si la fonction ne renvoie rien de significatif, le type unitaire est supposé. ().

Un détail important : la dernière expression d'une fonction (ou de tout bloc) ne se terminant pas par un point-virgule est considérée comme la valeur de retour implicite. Vous pouvez utiliser return pour les premiers retoursMais dans le code idiomatique, on omet souvent simplement l'expression finale. ;.

Le flux de contrôle est géré avec les classiques. if/elseboucles loop, while y forDans Rust, if Il s'agit d'une expression qui renvoie une valeurvous pouvez donc l'utiliser directement dans un letà condition que les branches renvoient le même type. Boucles for Ils itèrent généralement sur des plages ou des collections d'itérateurs et constituent l'option recommandée à la place des index manuels.

Pour documenter le code et faciliter la tâche à ceux qui viendront après (y compris vous-même dans un mois), vous pouvez utiliser commentaires de ligne avec // ou bloquer avec /* ... */De plus, Rust propose des commentaires de documentation avec /// qui deviennent des documents générés, bien que cela corresponde davantage aux grands projets.

Propriété, prêt et durée de vie : les fondements de la sécurité de la mémoire

Nous arrivons ici au cœur du modèle de mémoire de Rust : le système de propriété, emprunt et durées de vieCes règles garantissent que les références sont toujours valides et que la mémoire est libérée en toute sécurité sans accumulation de données inutiles.

Les règles fondamentales de la propriété sont simples à énoncer, même si elles peuvent être difficiles à intérioriser au premier abord : Chaque valeur appartient à un seul propriétaire.Il ne peut y avoir qu'un seul propriétaire à la fois ; et lorsque le propriétaire quitte son périmètre, la valeur est détruite et sa mémoire est libérée. Ceci s'applique, par exemple, à un String: une fois le bloc dans lequel elle a été déclarée exécuté, elle est automatiquement invoquée. drop ce qui libère la mémoire du tas.

Lorsque vous assignez une valeur valide à une autre variable ou que vous la transmettez par valeur à une fonction, la propriété est déplacée. Cela signifie que La variable d'origine cesse d'être valide après le déplacement.Cette sémantique des mouvements évite les doubles libérations, car il n'y a jamais deux propriétaires qui tentent de libérer la même ressource.

Pour permettre à plusieurs parties du programme d'accéder à la même valeur sans en changer la propriété, Rust introduit les références et l'emprunt. Lorsqu'on emprunte, on crée une référence. &T (immuable) ou &mut T (modifiable) à la valeur sans transfert de propriété. Le prêt est limité par les règles du vérificateur de prêts., qui vérifie que les références ne survivent pas aux données auxquelles elles pointent et que les accès mutables et partagés ne sont pas dangereusement mélangés.

Les règles du prêt peuvent être résumées comme suit : à tout moment, vous pouvez soit avoir références immuables multiples à une valeur, ou une seule référence mutableMais pas les deux en même temps. Cela élimine les risques de concurrence dans la mémoire partagée : soit il y a plusieurs lecteurs, soit il y a un seul écrivain ; jamais de lecture et d’écriture simultanées sur les mêmes données au même instant.

Types composites : structures, énumérations et pointeurs intelligents

Rust offre plusieurs façons de regrouper des données connexes en structures plus riches, à commencer par structuresUne structure vous permet de définir un type personnalisé avec des champs nommés, par exemple un utilisateur avec un e-mail, un nom, un statut d'activité et un compteur de connexions.

Pour créer une instance d'une structure, il faut renseigner tous ses champs. On peut également déclarer la variable qui la contient comme mutable afin de pouvoir modifier ses valeurs ultérieurement. Il existe aussi la syntaxe de mise à jour de structure, qui permet de créer une nouvelle instance en réutilisant certains champs d'une instance existante. ..otro_struct.

Les énumérations Ils constituent un autre pilier essentiel : ils permettent de définir un type qui peut prendre plusieurs variantes, chacune avec ses propres données associées ou sans. Un exemple classique est une énumération pour les adresses IP, avec une seule variante. V4 qui stocke quatre octets et un autre V6 qui stocke une chaîne de caractères au format IPv6.

La bibliothèque standard de Rust comprend deux énumérations très importantes : Option<T> y Result<T, E>Le premier représente la présence ou l'absence d'une valeur (quelque chose ou rien) et sert à éviter les pointeurs nuls ; le second modélise les opérations qui peuvent renvoyer un résultat correct ou une erreur, exigeant que la gestion des erreurs soit explicite et sécurisée.

Pour gérer la mémoire dynamique et partager des données, Rust possède pointeurs intelligents como Box<T>, qui déplace une valeur vers le tas et maintient une propriété unique ; Rc<T>, un compteur de références partagé pour les environnements monothread ; et Arc<T>, semblable à Rc mais sans danger pour le traitement multithread. Leur utilisation correcte est cruciale lorsqu'on combine mémoire dynamique et concurrence.

Cargaison et écosystème des caisses

Cargo est le ciment qui maintient l'écosystème Rust uni : gère la compilation, les dépendances et le cycle de vie du projetChaque projet possède un fichier Cargo.toml qui fait office de manifeste, déclarant le nom, la version, l'édition linguistique et les dépendances externes.

  Corrigé : erreur du pilote de bus PCI interne Windows 10

La section Ce fichier vous permet de lister les crates tiers avec leurs versions. Lorsque vous exécutez cargo build o cargo runCargo télécharge automatiquement ces crates depuis crates.io, les compile et les intègre à votre projet. C'est aussi simple que cela d'ajouter, par exemple, des générateurs de nombres aléatoires, des frameworks web ou des bibliothèques cryptographiques.

Parmi les commandes les plus courantes, on trouve : cargo new pour démarrer des projets binaires o cargo new --lib pour les bibliothèques ; cargo build compiler en mode débogage ; cargo build --release pour obtenir une version optimisée et orientée vers la production ; et cargo test pour exécuter la série de tests.

cargo check Il mérite une mention spéciale : il compile le code jusqu’à un point intermédiaire sans générer de binaire, ce qui le rend être très rapide pour détecter les erreurs de compilationIl est idéal pour itérer rapidement, tandis que le vérificateur d'emprunts signale les problèmes liés aux propriétés, aux références et aux durées de vie.

Grâce à cet écosystème, il est courant de structurer ses projets en petits modules bien définis, en partageant du code entre eux et en réutilisant les solutions créées par la communauté. Pour la gestion avancée de la concurrence, par exemple, vous trouverez des modules comme Tokio pour la programmation asynchrone ou Crossbeam pour les structures de données concurrentes hautes performances.

Concurrence en Rust : threads, mutex, canaux et opérations atomiques

La concurrence est l'une des raisons pour lesquelles Rust suscite autant d'intérêt : elle permet de tirer parti des processeurs multicœurs. sans tomber dans les erreurs typiques des threads et de la mémoire partagéeSi vous abordez ces sujets pour la première fois, il est utile de faire la distinction entre plusieurs concepts.

La concurrence consiste à exécuter plusieurs tâches qui se chevauchent dans le temps, sur un ou plusieurs cœurs. En Rust, vous pouvez créer des threads système pour effectuer des tâches en parallèle, et le langage vous guide pour garantir la sécurité des échanges de données entre eux. Une erreur classique est la condition de concurrence, où deux threads accèdent et modifient des données simultanément, et le résultat dépend de l'ordre d'exécution — un problème très difficile à déboguer.

Pour coordonner l'accès aux données partagées, Rust s'appuie sur des primitives telles que mutexqui garantissent l'exclusion mutuelle : un seul thread peut entrer dans la section critique à la fois. En combinaison avec Arc<T> Pour partager la propriété entre les threads, il est possible de construire des structures de données partagées qui respectent les règles de propriété et d'emprunt.

Une autre forme courante de communication inter-threads, fortement encouragée en Rust, est le passage de messages via filièresUn canal possède une extrémité d'émission et une extrémité de réception ; les threads y transmettent des messages (valeurs), ce qui réduit l'utilisation de la mémoire partagée mutable et simplifie le raisonnement sur l'état du système.

Lorsque vous approfondissez l'analyse de la concurrence de bas niveau, les éléments suivants apparaissent : types atomiquesLes variables atomiques sont accessibles via des opérations indivisibles du point de vue d'un thread. Ceci permet l'implémentation de compteurs partagés, d'indicateurs d'état, de files d'attente sans verrou, et bien plus encore. La maîtrise des variables atomiques requiert la compréhension des modèles de mémoire et des commandes d'accès ; c'est pourquoi de nombreux développeurs préfèrent commencer par les mutex et les canaux avant d'approfondir ces détails.

Premiers pas et ressources pour l'apprentissage de la concurrence et de l'atomicité

Si vous entrez dans l'arène sans aucune expérience préalable, la solution la plus sage est construire une base solide de concepts généraux Avant d'aborder des outils avancés comme les types atomiques de Rust, il est conseillé de se familiariser progressivement avec ces concepts. Des ouvrages tels que « Programming Rust » proposent une introduction graduelle, mais il est normal que les livres consacrés aux types atomiques et aux verrous paraissent complexes au premier abord.

Pour plus de facilité, il est conseillé de se familiariser d'abord avec Fils traditionnels, exclusion mutuelle et transmission de messages en Rust. Jouez avec des exemples de std::thread, std::sync::Mutex, std::sync::Arc et les canaux de std::sync::mpsc Cela vous aide à comprendre comment le compilateur vous guide et quelles erreurs il évite.

En parallèle, il est fortement recommandé de consulter des ressources d'introduction à la concurrence en général, même si elles ne sont pas axées sur Rust : comprendre ce que sont les conditions de concurrence, ce que signifie le blocage, ce qu'implique la mémoire partagée par rapport à la transmission de messages et comment les verrous sont utilisés. Une fois que ces concepts vous seront devenus naturels, la physique atomique cessera d'être de la « magie noire ». et ils deviennent un simple outil, certes très fragile.

Lorsque vous reviendrez à des textes plus avancés sur les opérations atomiques et les verrous en Rust, il vous sera beaucoup plus facile de suivre le raisonnement si vous comprenez déjà le problème que chaque construction tente de résoudre : d’un simple compteur thread-safe aux structures sans verrou qui minimisent les conflits.

En définitive, Rust offre à la fois des primitives de haut niveau et des outils de très bas niveau, et l'essentiel est de toujours choisir le niveau d'abstraction le plus sûr qui résout votre problème, en recourant au code atomique. unsafe uniquement lorsque cela apporte une réelle valeur ajoutée et que vous en comprenez pleinement les implications.

Cet écosystème complet de types, de propriété, d'emprunts, de caisses, d'outils et de primitives de concurrence se combine pour offrir un langage dans lequel écrire logiciel rapide, robuste et maintenableCela minimise de nombreux types d'erreurs qui ont historiquement entravé la programmation système. En vous exerçant sur de petits projets, des exercices comme Rustlings et en consultant la documentation officielle, ces concepts, qui vous paraissent aujourd'hui comme des règles strictes, deviendront un allié précieux vous alertant avant que le problème n'atteigne la production.

Introduction au langage Rust avec des exemples-0
Article connexe:
Introduction complète à Rust : un guide pratique pour débutants avec des exemples