Introduction à Rust
Rust est un langage de programmation système moderne développé par Mozilla. Rust combine les performances de C/C++ avec la sécurité mémoire, sans garbage collector.
🦀 Qu'est-ce que Rust ?
Rust est un langage de programmation compilé, statiquement typé, et sécurisé en mémoire. Rust garantit la sécurité mémoire à la compilation sans sacrifier les performances.
💡 Pourquoi Rust est si populaire ?
- Sécurité mémoire - Garantit la sécurité mémoire à la compilation, pas de segfaults
- Performance - Performances comparables à C/C++, sans garbage collector
- Concurrence - Système de propriété (ownership) pour une concurrence sûre
- Expressivité - Syntaxe moderne, pattern matching, traits
- Croissance - Langage le plus aimé selon Stack Overflow depuis plusieurs années
- Écosystème - Cargo (gestionnaire de paquets), crates.io (bibliothèques)
🚀 Pourquoi apprendre Rust ?
Rust est un excellent choix pour le développement système et les applications performantes :
- ✅ Sécurité - Pas de segfaults, pas de data races, sécurité garantie à la compilation
- ✅ Performance - Aussi rapide que C/C++, sans les risques
- ✅ Systèmes - Parfait pour les systèmes embarqués, OS, navigateurs
- ✅ Très demandé - Utilisé par Mozilla, Microsoft, Dropbox, Cloudflare
- ✅ Futur - Langage en croissance rapide, adoption par les grandes entreprises
- ✅ WebAssembly - Excellent pour compiler vers WebAssembly
📋 Prérequis pour apprendre Rust
Pour apprendre Rust efficacement, il est recommandé d'avoir :
- ✅ Base en programmation - Comprendre les concepts de base (variables, conditions, boucles)
- ✅ Logique - Avoir une bonne compréhension de la logique de programmation
💡 Note importante : Pour compiler du code Rust, vous avez besoin de Rustup (installateur Rust). Installez-le depuis rustup.rs. Vous pouvez utiliser VS Code avec l'extension rust-analyzer, ou RustRover (IDE JetBrains).
🎯 Cas d'usage de Rust
Rust est utilisé dans de nombreux domaines :
- Systèmes - Développement de systèmes d'exploitation, drivers, firmware
- WebAssembly - Compilation vers WebAssembly pour le web
- Blockchain - Développement de blockchains et smart contracts
- Outils CLI - Outils en ligne de commande performants
- Gaming - Moteurs de jeux, systèmes de rendu
📝 Syntaxe de base
La syntaxe Rust est moderne et expressive. Rust utilise des accolades {} pour définir les blocs de code et nécessite un point-virgule ; à la fin des instructions.
# Premier programme Python
print("Bonjour, monde !")
# Variables
nom = "NiangProgrammeur"
age = 25
# F-strings pour formater les chaînes (Python 3.6+)
print(f"Je m'appelle {nom} et j'ai {age} ans")
# Opérations simples
resultat = 10 + 5
print(f"10 + 5 = {resultat}")
💡 Points importants sur la syntaxe Rust :
- Rust utilise des accolades
{}pour définir les blocs de code - Les commentaires utilisent
//pour une ligne ou/* */pour plusieurs lignes - Point-virgule obligatoire
;à la fin de chaque instruction - Pattern matching - Syntaxe puissante avec
match - Fonction main - Point d'entrée :
fn main() - Conventions - Utilisez snake_case pour les variables et fonctions
🔍 Exemple de syntaxe détaillée
Voici un exemple complet montrant plusieurs aspects de la syntaxe Rust :
# Définition d'une fonction
def calculer_moyenne(nombres):
"""Calcule la moyenne d'une liste de nombres."""
if len(nombres) == 0:
return 0
somme = sum(nombres)
moyenne = somme / len(nombres)
return moyenne
# Utilisation
notes = [15, 18, 12, 20, 16]
moyenne = calculer_moyenne(notes)
print(f"La moyenne est : {moyenne}")
🔤 Variables
En Rust, les variables sont immuables par défaut. Utilisez mut pour rendre une variable mutable. Rust est un langage statiquement typé.
# Déclaration de variables
nom = "Python" # String (chaîne de caractères)
age = 30 # Integer (entier)
prix = 19.99 # Float (nombre décimal)
est_actif = True # Boolean (booléen)
valeur_nulle = None # NoneType (valeur nulle)
# Affichage
print(nom)
print(age)
print(prix)
print(est_actif)
print(valeur_nulle)
# Réassignation (changement de type)
variable = 10
print(type(variable)) #
variable = "Dix"
print(type(variable)) #
# Noms de variables valides
nom_utilisateur = "Bassirou"
age_utilisateur = 25
_privé = "variable privée"
CONSTANTE = 3.14159 # Convention pour les constantes
📌 Règles pour les noms de variables :
- Doivent commencer par une lettre ou un underscore
_ - Peuvent contenir des lettres, chiffres et underscores
- Sont sensibles à la casse
- Ne peuvent pas être des mots-clés Rust
- Convention : utilisez
snake_casepour les variables
📊 Types de données
Rust a plusieurs types de données intégrés. Voici les principaux :
# Types de base (scalaires)
texte = "Hello" # str (string)
nombre = 42 # int (integer)
decimal = 3.14 # float (floating point)
booleen = True # bool (boolean)
valeur_nulle = None # NoneType
# Collections (structures de données)
liste = [1, 2, 3, 4, 5] # list (liste ordonnée, modifiable)
tuple = (1, 2, 3) # tuple (liste ordonnée, immuable)
dictionnaire = {"nom": "Python", "age": 30} # dict (paires clé-valeur)
ensemble = {1, 2, 3, 4} # set (ensemble unique, non ordonné)
# Vérifier le type
print(type(texte)) #
print(type(nombre)) #
print(type(liste)) #
print(type(dictionnaire)) #
# Conversion de types
age_str = str(25) # Convertir en string
age_int = int("25") # Convertir en entier
prix_float = float("19.99") # Convertir en décimal
📚 Types de données Rust :
- String, &str - Chaînes de caractères
- i8, i16, i32, i64, i128 - Entiers signés
- u8, u16, u32, u64, u128 - Entiers non signés
- f32, f64 - Nombres décimaux
- bool - Booléens (true/false)
- char - Caractère Unicode (4 bytes)
- Array, Vec - Tableaux et vecteurs
🔢 Opérateurs
Rust supporte les opérateurs arithmétiques, de comparaison, logiques et d'assignation :
# Opérateurs arithmétiques
a = 10
b = 3
print(a + b) # Addition: 13
print(a - b) # Soustraction: 7
print(a * b) # Multiplication: 30
print(a / b) # Division: 3.3333333333333335
print(a // b) # Division entière: 3
print(a % b) # Modulo (reste): 1
print(a ** b) # Puissance: 1000
# Opérateurs de comparaison
print(a > b) # True (supérieur à)
print(a < b) # False (inférieur à)
print(a >= b) # True (supérieur ou égal)
print(a <= b) # False (inférieur ou égal)
print(a == b) # False (égalité)
print(a != b) # True (différent)
# Opérateurs logiques
x = True
y = False
print(x and y) # False (ET logique)
print(x or y) # True (OU logique)
print(not x) # False (NON logique)
# Opérateurs d'assignation
c = 5
c += 3 # Équivalent à c = c + 3 (c devient 8)
c -= 2 # Équivalent à c = c - 2 (c devient 6)
c *= 2 # Équivalent à c = c * 2 (c devient 12)
c /= 3 # Équivalent à c = c / 3 (c devient 4.0)
# Opérateurs d'identité
liste1 = [1, 2, 3]
liste2 = [1, 2, 3]
liste3 = liste1
print(liste1 is liste2) # False (objets différents)
print(liste1 is liste3) # True (même objet)
print(liste1 == liste2) # True (valeurs égales)
🔀 Structures conditionnelles
Rust utilise if, else if et else pour les conditions. Rust supporte aussi match pour le pattern matching.
# Structure if simple
age = 20
if age >= 18:
print("Vous êtes majeur")
else:
print("Vous êtes mineur")
# Structure if/elif/else
age = 15
if age >= 18:
print("Vous êtes majeur")
print("Vous pouvez voter")
elif age >= 13:
print("Vous êtes adolescent")
elif age >= 6:
print("Vous êtes enfant")
else:
print("Vous êtes un bébé")
# Conditions multiples
note = 85
if note >= 90:
mention = "Excellent"
elif note >= 80:
mention = "Très bien"
elif note >= 70:
mention = "Bien"
elif note >= 60:
mention = "Assez bien"
else:
mention = "Insuffisant"
print(f"Votre mention : {mention}")
# Opérateur ternaire (expression conditionnelle)
age = 20
statut = "Majeur" if age >= 18 else "Mineur"
print(statut)
# Conditions avec and/or
age = 25
permis = True
if age >= 18 and permis:
print("Vous pouvez conduire")
else:
print("Vous ne pouvez pas conduire")
🔄 Boucles
Rust propose plusieurs types de boucles : loop, while, et for :
# Boucle for avec range()
for i in range(5):
print(i) # Affiche 0, 1, 2, 3, 4
# range() avec début et fin
for i in range(1, 6):
print(i) # Affiche 1, 2, 3, 4, 5
# range() avec pas
for i in range(0, 10, 2):
print(i) # Affiche 0, 2, 4, 6, 8
# Boucle for avec liste
fruits = ["pomme", "banane", "orange"]
for fruit in fruits:
print(f"J'aime les {fruit}")
# Boucle for avec index (enumerate)
fruits = ["pomme", "banane", "orange"]
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# Boucle while
compteur = 0
while compteur < 5:
print(compteur)
compteur += 1
# Boucle while avec break
compteur = 0
while True:
print(compteur)
compteur += 1
if compteur >= 5:
break # Sortir de la boucle
# continue (passer à l'itération suivante)
for i in range(10):
if i % 2 == 0: # Si i est pair
continue # Passer au suivant
print(i) # Affiche seulement les impairs: 1, 3, 5, 7, 9
# Boucle for avec else
for i in range(5):
print(i)
else:
print("Boucle terminée") # Exécuté si la boucle se termine normalement
⚙️ Fonctions
Les fonctions en Rust sont définies avec fn. Rust supporte les fonctions avec plusieurs valeurs de retour via les tuples.
# Fonction simple (sans paramètres)
def dire_bonjour():
print("Bonjour !")
dire_bonjour() # Appel de la fonction
# Fonction avec paramètres
def saluer(nom):
return f"Bonjour, {nom} !"
message = saluer("Python")
print(message) # "Bonjour, Python !"
# Fonction avec plusieurs paramètres
def additionner(a, b):
return a + b
resultat = additionner(5, 3)
print(resultat) # 8
# Fonction avec paramètres par défaut
def saluer_personne(nom, message="Bonjour"):
return f"{message}, {nom} !"
print(saluer_personne("Bassirou")) # "Bonjour, Bassirou !"
print(saluer_personne("Bassirou", "Salut")) # "Salut, Bassirou !"
# Fonction avec arguments nommés
def creer_personne(nom, age, ville="Dakar"):
return f"{nom}, {age} ans, habite à {ville}"
print(creer_personne("Bassirou", 25))
print(creer_personne(age=25, nom="Bassirou", ville="Thiès"))
# Fonction avec *args (arguments variables)
def additionner_nombres(*args):
return sum(args)
print(additionner_nombres(1, 2, 3, 4, 5)) # 15
# Fonction avec **kwargs (arguments nommés variables)
def afficher_info(**kwargs):
for cle, valeur in kwargs.items():
print(f"{cle}: {valeur}")
afficher_info(nom="Bassirou", age=25, ville="Dakar")
# Fonction lambda (fonction anonyme)
carre = lambda x: x ** 2
print(carre(5)) # 25
# Utilisation de lambda avec map()
nombres = [1, 2, 3, 4, 5]
carres = list(map(lambda x: x ** 2, nombres))
print(carres) # [1, 4, 9, 16, 25]
📋 Ownership & Borrowing
Le système de propriété (ownership) de Rust garantit la sécurité mémoire. Les emprunts (borrowing) permettent d'accéder aux données sans les posséder.
# ========== LISTES ==========
# Création de listes
nombres = [1, 2, 3, 4, 5]
fruits = ["pomme", "banane", "orange"]
liste_mixte = [1, "deux", 3.0, True]
# Accès aux éléments (index commence à 0)
print(fruits[0]) # "pomme" (premier élément)
print(fruits[-1]) # "orange" (dernier élément)
# Modification
fruits[1] = "mangue" # Remplacer "banane" par "mangue"
# Méthodes des listes
fruits.append("kiwi") # Ajouter à la fin
fruits.insert(1, "ananas") # Insérer à l'index 1
fruits.remove("pomme") # Supprimer un élément
fruits.pop() # Supprimer le dernier élément
fruits.pop(0) # Supprimer l'élément à l'index 0
# Autres méthodes utiles
print(len(fruits)) # Longueur de la liste
print(fruits.count("banane")) # Compter les occurrences
fruits.sort() # Trier la liste
fruits.reverse() # Inverser la liste
# Slicing (tranches)
nombres = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nombres[2:5]) # [2, 3, 4] (de l'index 2 à 4)
print(nombres[:3]) # [0, 1, 2] (du début à l'index 2)
print(nombres[3:]) # [3, 4, 5, 6, 7, 8, 9] (de l'index 3 à la fin)
print(nombres[::2]) # [0, 2, 4, 6, 8] (tous les 2 éléments)
# ========== DICTIONNAIRES ==========
# Création de dictionnaires
personne = {
"nom": "Bassirou",
"age": 25,
"ville": "Dakar"
}
# Accès aux valeurs
print(personne["nom"]) # "Bassirou"
print(personne.get("age")) # 25 (méthode get() plus sûre)
print(personne.get("email", "Non renseigné")) # Valeur par défaut
# Modification et ajout
personne["age"] = 26 # Modifier
personne["email"] = "bassirou@example.com" # Ajouter
# Méthodes des dictionnaires
print(personne.keys()) # Toutes les clés
print(personne.values()) # Toutes les valeurs
print(personne.items()) # Toutes les paires clé-valeur
# Parcourir un dictionnaire
for cle, valeur in personne.items():
print(f"{cle}: {valeur}")
# Supprimer
del personne["email"] # Supprimer une clé
personne.pop("ville") # Supprimer et retourner la valeur
📦 Structs & Enums
Les structs permettent de regrouper des données. Les enums permettent de définir des types avec plusieurs variantes.
# Importer un module complet
import math
print(math.sqrt(16)) # 4.0 (racine carrée)
print(math.pi) # 3.141592653589793
print(math.cos(0)) # 1.0
# Importer avec un alias
import datetime as dt
maintenant = dt.datetime.now()
print(maintenant)
# Importer des fonctions spécifiques
from math import sqrt, pi
print(sqrt(25)) # 5.0
print(pi) # 3.141592653589793
# Importer tout d'un module (non recommandé)
from math import *
print(sin(0)) # 0.0
# Modules standards utiles
import random
print(random.randint(1, 100)) # Nombre aléatoire entre 1 et 100
import os
print(os.getcwd()) # Répertoire courant
import sys
print(sys.version) # Version de Python
# Créer son propre module
# Créer un fichier mon_module.py avec :
# def ma_fonction():
# return "Hello from module"
#
# Puis l'importer :
# import mon_module
# print(mon_module.ma_fonction())
🏗️ Traits
Les traits définissent des comportements partagés. Les traits sont similaires aux interfaces dans d'autres langages.
# Définir une classe
class Personne:
# Constructeur (méthode spéciale __init__)
def __init__(self, nom, age):
self.nom = nom # Attribut d'instance
self.age = age
# Méthode d'instance
def se_presenter(self):
return f"Je m'appelle {self.nom} et j'ai {self.age} ans"
def avoir_ans(self, annees):
self.age += annees
return f"Dans {annees} ans, j'aurai {self.age} ans"
# Créer des objets (instances)
personne1 = Personne("Bassirou", 25)
personne2 = Personne("Aminata", 30)
# Utiliser les méthodes
print(personne1.se_presenter())
print(personne2.se_presenter())
print(personne1.avoir_ans(5))
# Accéder aux attributs
print(personne1.nom)
print(personne1.age)
# Classe avec attributs de classe
class Voiture:
# Attribut de classe (partagé par toutes les instances)
nombre_voitures = 0
def __init__(self, marque, modele):
self.marque = marque
self.modele = modele
Voiture.nombre_voitures += 1
def __str__(self):
return f"{self.marque} {self.modele}"
voiture1 = Voiture("Toyota", "Corolla")
voiture2 = Voiture("Honda", "Civic")
print(f"Nombre de voitures créées : {Voiture.nombre_voitures}")
# Héritage
class Etudiant(Personne):
def __init__(self, nom, age, ecole):
super().__init__(nom, age) # Appeler le constructeur parent
self.ecole = ecole
def etudier(self):
return f"{self.nom} étudie à {self.ecole}"
etudiant = Etudiant("Bassirou", 25, "UCAD")
print(etudiant.se_presenter()) # Méthode héritée
print(etudiant.etudier()) # Méthode spécifique
📁 Manipulation de fichiers
Rust permet de lire et écrire dans des fichiers avec le package std::fs et std::io.
# Écrire dans un fichier (mode 'w' = write)
with open("fichier.txt", "w", encoding="utf-8") as f:
f.write("Bonjour Python !\n")
f.write("Ceci est la deuxième ligne\n")
# Lire un fichier (mode 'r' = read)
with open("fichier.txt", "r", encoding="utf-8") as f:
contenu = f.read()
print(contenu)
# Lire ligne par ligne
with open("fichier.txt", "r", encoding="utf-8") as f:
for ligne in f:
print(ligne.strip()) # strip() enlève les sauts de ligne
# Lire toutes les lignes dans une liste
with open("fichier.txt", "r", encoding="utf-8") as f:
lignes = f.readlines()
print(lignes)
# Ajouter à un fichier (mode 'a' = append)
with open("fichier.txt", "a", encoding="utf-8") as f:
f.write("Nouvelle ligne ajoutée\n")
# Modes de fichier
# 'r' - Lecture (défaut)
# 'w' - Écriture (écrase le fichier existant)
# 'a' - Ajout (ajoute à la fin)
# 'x' - Création exclusive (erreur si existe)
# 'b' - Mode binaire (rb, wb)
# 't' - Mode texte (défaut, rt, wt)
# '+' - Lecture et écriture (r+, w+, a+)
# Gestion d'erreurs
try:
with open("fichier_inexistant.txt", "r") as f:
contenu = f.read()
except FileNotFoundError:
print("Le fichier n'existe pas")
except PermissionError:
print("Permission refusée")
except Exception as e:
print(f"Erreur : {e}")
💡 Bonne pratique : Utilisez ? pour propager les erreurs ou unwrap() pour les erreurs fatales. Utilisez Result pour gérer les erreurs proprement.
🎓 Prochaines étapes
Félicitations ! Vous avez maintenant une solide base en Rust.
✅ Ce que vous avez appris :
- Syntaxe Rust et variables
- Types de données (String, i32, f64, bool)
- Opérateurs et expressions
- Structures conditionnelles (if, match)
- Boucles (loop, while, for)
- Fonctions et tuples
- Ownership et borrowing
- Structs et enums
- Traits
- Manipulation de fichiers
🚀 Pour aller plus loin :
- Ownership avancé - Lifetimes, borrowing rules
- Pattern matching - Match expressions avancées
- Traits - Définir et implémenter des traits
- Error handling - Result et Option
- Concurrence - Threads, channels, async/await