Passage par valeur ou par référence
Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 21 sur 107.
Go est un langage à passage par valeur. Lorsque vous passez une variable à une fonction, Go crée une copie de cette valeur. Cela signifie que les modifications à l'intérieur de la fonction n'affectent pas la variable d'origine.
func double(n int) {
n = n * 2
}
func main() {
x := 10
double(x)
fmt.Println(x) // 10 (inchangé)
}Il en va de même pour les structures. Passer une structure à une fonction copie tous ses champs, de sorte que les modifications effectuées à l'intérieur de la fonction sont perdues.
type Person struct {
Name string
Age int
}
func birthday(p Person) {
p.Age++
}
func main() {
alice := Person{Name: "Alice", Age: 30}
birthday(alice)
fmt.Println(alice.Age) // 30 (inchangé)
}Pour modifier la valeur d'origine, passez plutôt un pointeur. Le pointeur lui-même est copié, mais il pointe toujours vers la même adresse mémoire, ce qui vous permet de modifier les données d'origine.
func birthday(p *Person) {
p.Age++
}
func main() {
alice := Person{Name: "Alice", Age: 30}
birthday(&alice)
fmt.Println(alice.Age) // 31 (modifié !)
}Utilisez des pointeurs lorsque vous avez besoin de modifier la valeur d'origine ou lors du passage de structures volumineuses pour éviter une copie coûteuse. Utilisez des valeurs lorsque vous souhaitez protéger les données d'origine contre des modifications involontaires.
Défi
FacileConstruisons un système de panier qui illustre la différence entre le passage de structs par valeur et par pointeur. Tu verras directement que seuls les paramètres pointeurs peuvent modifier les données d’origine.
Tu organiseras ton code sur deux fichiers :
cart.go: définis une structCartItemavec les champsName(string),Price(float64) etQuantity(int). Crée deux fonctions qui tentent de mettre à jour la quantité :UpdateQuantityByValueprend unCartItem(par valeur) et une nouvelle quantité, puis définit la quantité de l’article sur cette nouvelle valeurUpdateQuantityByPointerprend un*CartItem(pointeur) et une nouvelle quantité, puis définit la quantité de l’article sur cette nouvelle valeur
TotalsurCartItemqui renvoie le prix multiplié par la quantité.main.go: lis les détails de l’article depuis l’entrée, crée un CartItem, puis montre les deux approches de mise à jour. Essaie d’abord la mise à jour avec la fonction par valeur et affiche le résultat, puis effectue la mise à jour avec la fonction par pointeur et affiche à nouveau le résultat.
Les entrées suivantes seront fournies :
- Ligne 1 : Nom de l’article
- Ligne 2 : Prix (float)
- Ligne 3 : Quantité initiale (entier)
- Ligne 4 : Nouvelle quantité à définir (entier)
Format de sortie :
Initial: [Name] x[Quantity] = $[Total]
After value update: [Name] x[Quantity] = $[Total]
After pointer update: [Name] x[Quantity] = $[Total]Par exemple, avec Laptop, 999.99, 1 et 3, ta sortie doit être :
Initial: Laptop x1 = $999.99
After value update: Laptop x1 = $999.99
After pointer update: Laptop x3 = $2999.97Remarque que la quantité reste à 1 après la mise à jour par valeur (la fonction a modifié une copie), mais passe à 3 après la mise à jour par pointeur (la fonction a modifié l’original). Formate les totaux avec deux décimales.
Essayez vous-même
package main
import (
"fmt"
)
func main() {
// Lire l'entrée
var name string
var price float64
var initialQty, newQty int
fmt.Scanln(&name)
fmt.Scanln(&price)
fmt.Scanln(&initialQty)
fmt.Scanln(&newQty)
// TODO: Créer un CartItem avec les valeurs d'entrée
// TODO: Afficher l'état initial en utilisant le format :
// fmt.Printf("Initial: %s x%d = $%.2f\n", ...)
// TODO: Essayer de mettre à jour la quantité en utilisant UpdateQuantityByValue
// Ensuite, afficher le résultat (remarquez que la quantité ne changera pas)
// TODO: Mettre à jour la quantité en utilisant UpdateQuantityByPointer
// Ensuite, afficher le résultat (remarquez que la quantité changera)
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO en Go
Fichiers externesEspace de travail et modules GoPackages et importsNoms exportés et non exportésIntroduction à la POO en GoStructs comme classesDéfinir des méthodes sur des structsRécepteurs pointeurs ou par valeurInitialisation des structsFonctions constructeursRécapitulatif - Calculatrice simple4Interfaces
Introduction aux interfacesImplémentation impliciteL’interface comme contratInterface vide (any)Assertion de typeCommutation de typeComposition d’interfacesInterfaces Stringer et ErrorRécapitulatif - Calculateur de formes7Encapsulation
Champs exportés vs non exportésEncapsulation au niveau du packageMéthodes Getter et SetterDissimulation de l’information en GoRécapitulatif – Fiches d’étudiants10Génériques (Go 1.18+)
Introduction aux génériquesParamètres de typeContraintes de typeStructures génériquesSolution de contournement pour les méthodes génériquesRécapitulatif - Collection générique2Plongée approfondie dans les types et les structs
Types de base et compositesDéfinitions de types personnalisésTags de structStructs anonymesStructs imbriquésValeurs zéro et valeurs par défautRécapitulatif - Carnet de contacts5La composition plutôt que l’héritage
Pourquoi Go n’a pas d’héritageBases de l’inclusion de structsPromotion des méthodesInclure plusieurs structsInclusion ou agrégationMasquage des méthodes inclusesRécapitulatif : hiérarchie des employés8Gestion des erreurs et POO
L’interface errorTypes d’erreurs personnalisésEnrobage des erreurs (fmt.Errorf)Erreurs sentinelleserrors.Is() et errors.As()Panic, Defer et RecoverRécapitulatif - Analyseur de fichiers11Bibliothèque standard et POO
io.Reader et io.Writersort.InterfaceInterface fmt.Stringerencoding/json avec des structsInterface http.HandlerRécapitulatif - Modèles d’API REST14Modèles de conception – Partie 2
Modèle CommandeModèle AdaptateurModèle DécorateurModèle Méthode modèleModèle ÉtatModèle CompositeMiddleware comme décorateur3Pointeurs et mémoire
Notions de base des pointeurs en GoPointeurs vers des structuresPassage par valeur ou par référenceLa fonction new()Garbage collection en GoRécapitulatif - Constructeur de listes chaînées6Polymorphisme en Go
Polymorphisme via les interfacesDuck typing en GoRègles de satisfaction des interfacesCollections polymorphesInjection de dépendancesRécapitulatif – Processeur de paiements9Concurrence et POO
Bases des GoroutinesCanaux et communicationCanaux tamponnés ou non tamponnésInstruction selectsync.Mutex et sync.RWMutexsync.WaitGroupConception de structures thread-safeRécapitulatif - Pool de workersEntraînez-vous par vous-même : Compilateur Go en ligne