En Go, dès que tu passes une valeur, tu la copies. C'est la règle qui gouverne tout le reste.In Go, the moment you pass a value, you copy it. That's the rule governing everything else.
Le volume 5 nous a montré des structures qui partagent une mémoire sous-jacente — une slice et son tableau, une map et sa table. On pourrait en conclure que partager est la norme en Go. C'est l'exact contraire. Le comportement par défaut du langage, celui dont tout le reste découle, c'est la copie. Assigner une variable à une autre, passer un argument à une fonction, ranger une valeur dans un tableau ou la renvoyer d'une fonction : à chacun de ces gestes, Go duplique la valeur, champ par champ. Pas de référence implicite, pas de partage caché — une copie franche, dont les modifications n'ont aucun effet sur l'original. C'est vrai des entiers, c'est vrai des structs, c'est vrai des tableaux de taille fixe. Cette sémantique de valeur a deux visages, et tout l'art consiste à savoir lequel tu regardes. Côté pile, c'est un service : une copie ne peut pas être mutée à distance, donc une fonction qui reçoit ta struct ne peut pas, par mégarde, corrompre la tienne. Côté face, c'est un coût : une grosse struct recopiée à chaque appel, c'est de la mémoire et du temps dépensés à dupliquer. Comprendre la sémantique de valeur, c'est savoir reconnaître, à chaque passage, lequel des deux tu paies — et choisir un pointeur quand le coût l'emporte, ou quand tu veux justement muter l'original.Volume 5 showed us structures that share an underlying memory — a slice and its array, a map and its table. You might conclude that sharing is the norm in Go. It's the exact opposite. The language's default behavior, the one everything else flows from, is the copy. Assigning one variable to another, passing an argument to a function, storing a value in an array or returning it from a function: at each of these moves, Go duplicates the value, field by field. No implicit reference, no hidden sharing — a clean copy, whose modifications have no effect on the original. It's true of integers, true of structs, true of fixed-size arrays. This value semantics has two faces, and the whole craft is knowing which one you're looking at. Heads, it's a gift: a copy can't be mutated at a distance, so a function receiving your struct can't accidentally corrupt yours. Tails, it's a cost: a big struct re-copied on every call is memory and time spent duplicating. Understanding value semantics is knowing how to recognize, at each pass, which of the two you're paying — and choosing a pointer when the cost wins, or when you actually want to mutate the original.
type Point struct{ X, Y int } a := Point{1, 2} b := a // COPIE : b est un Point indépendant, champ par champ b.X = 99 fmt.Println(a) // {1 2} ← a intact, aucun lien avec b fmt.Println(b) // {99 2}
func reset(p Point) { // p est une COPIE de l'argument passé p.X = 0 // … on modifie la copie locale, pas l'original } a := Point{1, 2} reset(a) // a est copié dans p au moment de l'appel fmt.Println(a) // {1 2} ← reset n'a jamais touché le vrai a
La même opération — copier — est tantôt une protection, tantôt une dépense. Rien dans le code ne dit lequel ; c'est la taille de la valeur et ton intention qui tranchent. Tout le volume apprend à lire ce choix.The same operation — copying — is sometimes a protection, sometimes an expense. Nothing in the code says which; it's the value's size and your intent that decide. The whole volume teaches you to read that choice.
« Je passe une valeur ? alors je passe une copie — sauf si je passe un pointeur. » C'est la grille de lecture de tout le langage. Une fonction ne peut muter ce que tu lui donnes que si tu lui donnes l'adresse, pas la valeur. Le volume 5 était l'exception qui partage ; celui-ci est la règle qui isole. Et il révèle au passage pourquoi la slice et la map se comportaient si différemment : ce qu'on en copie, c'est leur en-tête, pas leur contenu."Am I passing a value? then I'm passing a copy — unless I pass a pointer." It's the reading grid for the entire language. A function can only mutate what you give it if you give it the address, not the value. Volume 5 was the exception that shares; this one is the rule that isolates. And it reveals along the way why the slice and the map behaved so differently: what you copy of them is their header, not their content.
Un point de vocabulaire, qu'on déplie au chapitre 3 : copier une valeur en Go, c'est dupliquer ses champs tels quels — pas suivre récursivement ce vers quoi ils pointent. Copier une struct qui contient un int et un bool donne deux champs neufs, totalement indépendants. Mais copier une struct qui contient une slice duplique l'en-tête de la slice — ses trois mots — sans dupliquer le tableau sous-jacent. Les deux copies pointent alors vers le même tableau. C'est une copie « de surface » (shallow), et c'est le pont exact entre ce volume et le précédent : la sémantique de valeur copie fidèlement, mais ce qu'elle copie d'une slice, c'est précisément la vue partagée qu'on a étudiée tout le volume 5.A point of vocabulary, unfolded in chapter 3: copying a value in Go duplicates its fields as they are — not recursively following what they point to. Copying a struct holding an int and a bool gives two fresh, fully independent fields. But copying a struct holding a slice duplicates the slice's header — its three words — without duplicating the underlying array. Both copies then point at the same array. It's a 'shallow' copy, and it's the exact bridge between this volume and the last: value semantics copies faithfully, but what it copies of a slice is precisely the shared view we studied all through volume 5.