En Go, la plupart des types de données intégrés (par exemple, int, float, struct) sont mutables lorsqu'ils sont déclarés comme variables, car lors du passage par valeur, toute la structure ou la valeur est copiée. Mais il y a une nuance : les slices, maps, et channels sont des types référencés avec leur propre logique interne de stockage des données.
Types de base :
x := 10 y := x // Ici, une copie de la valeur est créée, x et y ne sont pas liés entre eux y = 20 // x restera 10
Slices :
a := []int{1,2,3} b := a // référence au même tableau de base b[0] = 100 // maintenant a[0] == 100
C'est important si une fonction ou une méthode prend une structure ou un slice, car les changements peuvent soit affecter les données originales, soit non, en fonction du type de données et du mode de passage (par valeur ou par référence).
Question : "Si vous assignez un slice à un autre, obtenez-vous une copie profonde ou les deux pointent-elles vers les mêmes données ?"
Réponse : Lors d'une simple affectation de slices (b := a) — les deux pointent vers le même tableau de base, mais ont une longueur et une capacité indépendantes. Une modification à travers l'un des slices des données du tableau lui-même est visible dans l'autre.
Exemple :
a := []int{1,2,3} b := a b[0] = 42 fmt.Println(a) // [42 2 3]
Pour faire une copie profonde, on utilise copy :
c := make([]int, len(a)) copy(c, a) c[0] = 99 fmt.Println(a) // [42 2 3], c est une copie indépendante
Histoire
Le service de filtrage des données a commencé à renvoyer des résultats inattendus : Un développeur passait des slices entre plusieurs fonctions sans les copier, modifiant leur état. En raison des modifications des slices à différents endroits, la logique de l'application se cassait, et des bugs étranges dans les données apparaissaient, qui étaient difficiles à attraper.
Histoire
Perte de données après le passage d'une structure : Dans un projet, lors de la sérialisation des données, un champ obligatoire était accidentellement supprimé de la structure, car l'objet était passé par référence, et sa copie n'était pas créée. En conséquence, cela entraînait une perte d'informations critiques en production.
Histoire
Erreur de travail en parallèle avec map : Un développeur a copié une référence vers une map, pensant que les modifications n'affecteraient pas l'original, comme cela se produit dans d'autres langages. Cela a entraîné une course de données lors de l'utilisation dans différentes goroutines, provoquant des plantages de l'application.