La slice te piège par ce qu'elle partage en silence. La map te piège par ce qu'elle refuse, ouvertement.The slice traps you by what it silently shares. The map traps you by what it openly refuses.
La map est l'autre pilier du modèle de données de Go, et on l'utilise chaque jour : une table de hachage qui associe des clés à des valeurs, avec une lecture et une écriture en temps constant. Mais là où la slice cachait son danger — un cap invisible, un tableau partagé sans le dire — la map affiche le sien. Elle refuse trois choses que la plupart des langages offrent par confort, et elle le fait sciemment, parfois brutalement. D'abord, elle n'ordonne pas ses clés : deux parcours de la même map peuvent te les rendre dans deux ordres différents, et c'est voulu. Ensuite, sa valeur zéro — une map nil — se laisse lire mais pas écrire : la moindre assignation panique. Enfin, elle interdit l'accès concurrent : si une goroutine lit pendant qu'une autre écrit, le runtime n'essaie pas de réparer, il arrête net le programme. Trois refus, trois surprises — mais aucune n'est un accident. Chacune protège une vérité que d'autres langages préfèrent te cacher : sur le hachage, sur l'initialisation, sur la concurrence. Ce numéro prend les refus un par un, et montre ce qu'on met à la place.The map is the other pillar of Go's data model, and you use it every day: a hash table mapping keys to values, with constant-time read and write. But where the slice hid its danger — an invisible cap, an array shared without saying so — the map flaunts its own. It refuses three things most languages offer for comfort, and it does so knowingly, sometimes brutally. First, it doesn't order its keys: two passes over the same map can return them in two different orders, and that's intended. Second, its zero value — a nil map — can be read but not written: the slightest assignment panics. Third, it forbids concurrent access: if one goroutine reads while another writes, the runtime doesn't try to repair, it stops the program outright. Three refusals, three surprises — but none is an accident. Each protects a truth other languages prefer to hide from you: about hashing, about initialization, about concurrency. This issue takes the refusals one by one, and shows what you put in their place.
m := map[string]int{"a": 1, "b": 2} // une table de hachage, prête // 1. l'ordre d'itération est tiré au hasard à chaque parcours for k := range m { use(k) } // "a","b" ? "b","a" ? jamais garanti // 2. sa valeur zéro est nil — lisible, mais pas inscriptible var z map[string]int // nil z["x"] = 1 // panic: assignment to entry in nil map // 3. lue ET écrite par deux goroutines en même temps : // fatal error: concurrent map read and map write ← le runtime te tue
Aucun de ces refus n'est un oubli. Chacun rend visible une contrainte réelle que d'autres langages masquent — au prix d'un ordre illusoire, d'une initialisation magique, ou d'une corruption silencieuse. La map de Go préfère te dire non tout de suite.None of these refusals is an oversight. Each makes a real constraint visible that other languages mask — at the cost of an illusory order, a magic initialization, or a silent corruption. Go's map prefers to say no up front.
« Une map refuse exprès ; chaque refus garde une vérité — et m'indique quoi faire à la place. » On ne combat pas ces refus, on les lit. L'ordre ? trie les clés. La map nil ? alloue-la. La concurrence ? verrouille, ou prends un type fait pour ça. Trois surprises au premier contact, trois automatismes ensuite. Le numéro déplie chacune jusqu'à ce qu'elle devienne évidente."A map refuses on purpose; each refusal guards a truth — and tells me what to do instead." You don't fight these refusals, you read them. Order? sort the keys. Nil map? allocate it. Concurrency? lock it, or take a type built for it. Three surprises on first contact, three reflexes afterward. The issue unfolds each until it becomes obvious.
Une map range ses clés selon leur hachage : un nombre calculé à partir de la clé, qui détermine dans quel « casier » (bucket) elle atterrit. Cet emplacement n'a rien à voir avec l'ordre d'insertion, ni avec un quelconque tri — c'est une dispersion, faite pour répartir uniformément, pas pour ranger. Quand la map grandit, elle réorganise ses casiers, et les positions changent encore. Il n'existe donc pas d'ordre « naturel » à exposer : tout ordre qu'on observerait serait un artefact de l'implémentation du moment. Go pousse la logique au bout — il randomise volontairement le point de départ du parcours — pour t'interdire de t'appuyer sur un ordre qui n'existe pas vraiment.A map arranges its keys by their hash: a number computed from the key, deciding which 'bucket' it lands in. That spot has nothing to do with insertion order, nor with any sorting — it's a dispersion, made to spread evenly, not to arrange. When the map grows, it reorganizes its buckets, and positions shift again. So there's no 'natural' order to expose: any order you'd observe would be an artifact of the current implementation. Go takes the logic to its end — it deliberately randomizes the iteration's starting point — to forbid you from leaning on an order that doesn't truly exist.