[{"data":1,"prerenderedAt":3240},["ShallowReactive",2],{"page-\u002Fgo\u002F08-maps":3},{"id":4,"title":5,"body":6,"description":3233,"extension":3234,"meta":3235,"navigation":175,"path":3236,"seo":3237,"stem":3238,"__hash__":3239},"content\u002Fgo\u002F08-maps.md","08 — Maps",{"type":7,"value":8,"toc":3228},"minimark",[9,13,18,3224],[10,11,5],"h1",{"id":12},"_08-maps",[14,15,17],"h2",{"id":16},"hash-map-internals","Hash Map Internals",[19,20,22,288,292,3145,3211,3215],"code-wrapper",{"language":21},"go",[23,24,28],"pre",{"className":25,"code":26,"language":21,"meta":27,"style":27},"language-go shiki shiki-themes github-light github-dark","\u002F\u002F Go's map is a hash table with overflow buckets.\n\u002F\u002F ┌──────────────────────────────────────────────────────────────────┐\n\u002F\u002F │  hmap struct (runtime\u002Fmap.go)                                   │\n\u002F\u002F │   ├── count     int      — number of entries                    │\n\u002F\u002F │   ├── B         uint8    — log2 of bucket count (2^B buckets)   │\n\u002F\u002F │   ├── hash0      uint32   — hash seed (randomized per map)       │\n\u002F\u002F │   ├── buckets    unsafe.Pointer — array of 2^B buckets          │\n\u002F\u002F │   └── oldbuckets unsafe.Pointer — pre-growth buckets (for evac) │\n\u002F\u002F │                                                                  │\n\u002F\u002F │  Bucket (8 entries max):                                        │\n\u002F\u002F │   ├── tophash [8]uint8  — top byte of each key's hash            │\n\u002F\u002F │   ├── keys    [8]KeyType                                       │\n\u002F\u002F │   ├── values  [8]ValueType                                      │\n\u002F\u002F │   └── overflow *bucket  — linked list for >8 collisions         │\n\u002F\u002F │                                                                  │\n\u002F\u002F │  Lookup: hash(key) → bucket = hash & (2^B - 1)                  │\n\u002F\u002F │          scan tophash array for top byte match → full key compare│\n\u002F\u002F │          if bucket full, follow overflow pointer                 │\n\u002F\u002F │                                                                  │\n\u002F\u002F │  Growth: when load factor > 6.5 or too many overflow buckets:   │\n\u002F\u002F │          allocate 2x buckets, evacuate incrementally (not all   │\n\u002F\u002F │          at once — amortized, prevents latency spikes)          │\n\u002F\u002F └──────────────────────────────────────────────────────────────────┘\n\nfunc internals() {\n    m := make(map[string]int, 1000)  \u002F\u002F hint: pre-allocate ~1000 buckets\n    \u002F\u002F The hint is NOT a limit — the map grows as needed.\n    \u002F\u002F But pre-sizing avoids the incremental growth phase (rehashing).\n    \u002F\u002F Actual bucket count = next power of 2 >= hint.\n\n    \u002F\u002F Each bucket holds 8 entries. With 1000 entries and 8 per bucket:\n    \u002F\u002F   128 buckets minimum (2^7 = 128). The hint causes B=7.\n    \u002F\u002F Without the hint, the map starts with B=0 (1 bucket) and grows\n    \u002F\u002F incrementally, rehashing multiple times to reach B=7.\n}\n","",[29,30,31,40,46,52,58,64,70,76,82,88,94,100,106,112,118,123,129,135,141,146,152,158,164,170,177,192,235,241,247,253,258,264,270,276,282],"code",{"__ignoreMap":27},[32,33,36],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"sdCPZ","\u002F\u002F Go's map is a hash table with overflow buckets.\n",[32,41,43],{"class":34,"line":42},2,[32,44,45],{"class":38},"\u002F\u002F ┌──────────────────────────────────────────────────────────────────┐\n",[32,47,49],{"class":34,"line":48},3,[32,50,51],{"class":38},"\u002F\u002F │  hmap struct (runtime\u002Fmap.go)                                   │\n",[32,53,55],{"class":34,"line":54},4,[32,56,57],{"class":38},"\u002F\u002F │   ├── count     int      — number of entries                    │\n",[32,59,61],{"class":34,"line":60},5,[32,62,63],{"class":38},"\u002F\u002F │   ├── B         uint8    — log2 of bucket count (2^B buckets)   │\n",[32,65,67],{"class":34,"line":66},6,[32,68,69],{"class":38},"\u002F\u002F │   ├── hash0      uint32   — hash seed (randomized per map)       │\n",[32,71,73],{"class":34,"line":72},7,[32,74,75],{"class":38},"\u002F\u002F │   ├── buckets    unsafe.Pointer — array of 2^B buckets          │\n",[32,77,79],{"class":34,"line":78},8,[32,80,81],{"class":38},"\u002F\u002F │   └── oldbuckets unsafe.Pointer — pre-growth buckets (for evac) │\n",[32,83,85],{"class":34,"line":84},9,[32,86,87],{"class":38},"\u002F\u002F │                                                                  │\n",[32,89,91],{"class":34,"line":90},10,[32,92,93],{"class":38},"\u002F\u002F │  Bucket (8 entries max):                                        │\n",[32,95,97],{"class":34,"line":96},11,[32,98,99],{"class":38},"\u002F\u002F │   ├── tophash [8]uint8  — top byte of each key's hash            │\n",[32,101,103],{"class":34,"line":102},12,[32,104,105],{"class":38},"\u002F\u002F │   ├── keys    [8]KeyType                                       │\n",[32,107,109],{"class":34,"line":108},13,[32,110,111],{"class":38},"\u002F\u002F │   ├── values  [8]ValueType                                      │\n",[32,113,115],{"class":34,"line":114},14,[32,116,117],{"class":38},"\u002F\u002F │   └── overflow *bucket  — linked list for >8 collisions         │\n",[32,119,121],{"class":34,"line":120},15,[32,122,87],{"class":38},[32,124,126],{"class":34,"line":125},16,[32,127,128],{"class":38},"\u002F\u002F │  Lookup: hash(key) → bucket = hash & (2^B - 1)                  │\n",[32,130,132],{"class":34,"line":131},17,[32,133,134],{"class":38},"\u002F\u002F │          scan tophash array for top byte match → full key compare│\n",[32,136,138],{"class":34,"line":137},18,[32,139,140],{"class":38},"\u002F\u002F │          if bucket full, follow overflow pointer                 │\n",[32,142,144],{"class":34,"line":143},19,[32,145,87],{"class":38},[32,147,149],{"class":34,"line":148},20,[32,150,151],{"class":38},"\u002F\u002F │  Growth: when load factor > 6.5 or too many overflow buckets:   │\n",[32,153,155],{"class":34,"line":154},21,[32,156,157],{"class":38},"\u002F\u002F │          allocate 2x buckets, evacuate incrementally (not all   │\n",[32,159,161],{"class":34,"line":160},22,[32,162,163],{"class":38},"\u002F\u002F │          at once — amortized, prevents latency spikes)          │\n",[32,165,167],{"class":34,"line":166},23,[32,168,169],{"class":38},"\u002F\u002F └──────────────────────────────────────────────────────────────────┘\n",[32,171,173],{"class":34,"line":172},24,[32,174,176],{"emptyLinePlaceholder":175},true,"\n",[32,178,180,184,188],{"class":34,"line":179},25,[32,181,183],{"class":182},"svdQ7","func",[32,185,187],{"class":186},"sIsaT"," internals",[32,189,191],{"class":190},"ssxIu","() {\n",[32,193,195,198,201,204,207,210,213,216,219,222,225,229,232],{"class":34,"line":194},26,[32,196,197],{"class":190},"    m ",[32,199,200],{"class":182},":=",[32,202,203],{"class":186}," make",[32,205,206],{"class":190},"(",[32,208,209],{"class":182},"map",[32,211,212],{"class":190},"[",[32,214,215],{"class":182},"string",[32,217,218],{"class":190},"]",[32,220,221],{"class":182},"int",[32,223,224],{"class":190},", ",[32,226,228],{"class":227},"snvgF","1000",[32,230,231],{"class":190},")  ",[32,233,234],{"class":38},"\u002F\u002F hint: pre-allocate ~1000 buckets\n",[32,236,238],{"class":34,"line":237},27,[32,239,240],{"class":38},"    \u002F\u002F The hint is NOT a limit — the map grows as needed.\n",[32,242,244],{"class":34,"line":243},28,[32,245,246],{"class":38},"    \u002F\u002F But pre-sizing avoids the incremental growth phase (rehashing).\n",[32,248,250],{"class":34,"line":249},29,[32,251,252],{"class":38},"    \u002F\u002F Actual bucket count = next power of 2 >= hint.\n",[32,254,256],{"class":34,"line":255},30,[32,257,176],{"emptyLinePlaceholder":175},[32,259,261],{"class":34,"line":260},31,[32,262,263],{"class":38},"    \u002F\u002F Each bucket holds 8 entries. With 1000 entries and 8 per bucket:\n",[32,265,267],{"class":34,"line":266},32,[32,268,269],{"class":38},"    \u002F\u002F   128 buckets minimum (2^7 = 128). The hint causes B=7.\n",[32,271,273],{"class":34,"line":272},33,[32,274,275],{"class":38},"    \u002F\u002F Without the hint, the map starts with B=0 (1 bucket) and grows\n",[32,277,279],{"class":34,"line":278},34,[32,280,281],{"class":38},"    \u002F\u002F incrementally, rehashing multiple times to reach B=7.\n",[32,283,285],{"class":34,"line":284},35,[32,286,287],{"class":190},"}\n",[14,289,291],{"id":290},"declaration-and-the-comma-ok-idiom","Declaration and the Comma-OK Idiom",[19,293,294,603,607],{"language":21},[23,295,297],{"className":25,"code":296,"language":21,"meta":27,"style":27},"\u002F\u002F ┌────────────────────────────────────────────────────────────┐\n\u002F\u002F │ Declaration              │ Nil?    │ Can Write?            │\n\u002F\u002F │ ──────────────────────── │ ─────── │ ────────────────────── │\n\u002F\u002F │ var m map[K]V           │ yes     │ ❌ panic on write     │\n\u002F\u002F │ m = map[K]V{}           │ no      │ ✅                    │\n\u002F\u002F │ m = make(map[K]V)       │ no      │ ✅                    │\n\u002F\u002F │ m = make(map[K]V, n)   │ no      │ ✅ (pre-sized)        │\n\u002F\u002F └────────────────────────────────────────────────────────────┘\n\nfunc basics() {\n    m := map[string]int{\"a\": 1, \"b\": 2}\n    m[\"c\"] = 3\n    delete(m, \"a\")\n\n    \u002F\u002F Comma-ok: distinguish \"absent\" from \"zero value\"\n    v, ok := m[\"x\"]\n    if !ok {\n        \u002F\u002F \"x\" is not in the map\n        fmt.Println(\"missing\")\n    } else {\n        fmt.Println(\"value:\", v)\n    }\n\n    \u002F\u002F ⚠️ Without comma-ok, m[\"missing\"] returns the ZERO VALUE:\n    fmt.Println(m[\"nonexistent\"])  \u002F\u002F 0 — indistinguishable from a stored 0\n\n    \u002F\u002F Reading a nil map is safe (returns zero value):\n    var nilMap map[string]int\n    fmt.Println(nilMap[\"a\"])  \u002F\u002F 0 — no panic\n\n    \u002F\u002F Writing to a nil map PANICS:\n    \u002F\u002F nilMap[\"a\"] = 1  \u002F\u002F panic: assignment to entry in nil map\n}\n",[29,298,299,304,309,314,319,324,329,334,339,343,352,394,411,424,428,433,449,460,465,480,491,505,510,514,519,538,542,547,566,582,586,591,599],{"__ignoreMap":27},[32,300,301],{"class":34,"line":35},[32,302,303],{"class":38},"\u002F\u002F ┌────────────────────────────────────────────────────────────┐\n",[32,305,306],{"class":34,"line":42},[32,307,308],{"class":38},"\u002F\u002F │ Declaration              │ Nil?    │ Can Write?            │\n",[32,310,311],{"class":34,"line":48},[32,312,313],{"class":38},"\u002F\u002F │ ──────────────────────── │ ─────── │ ────────────────────── │\n",[32,315,316],{"class":34,"line":54},[32,317,318],{"class":38},"\u002F\u002F │ var m map[K]V           │ yes     │ ❌ panic on write     │\n",[32,320,321],{"class":34,"line":60},[32,322,323],{"class":38},"\u002F\u002F │ m = map[K]V{}           │ no      │ ✅                    │\n",[32,325,326],{"class":34,"line":66},[32,327,328],{"class":38},"\u002F\u002F │ m = make(map[K]V)       │ no      │ ✅                    │\n",[32,330,331],{"class":34,"line":72},[32,332,333],{"class":38},"\u002F\u002F │ m = make(map[K]V, n)   │ no      │ ✅ (pre-sized)        │\n",[32,335,336],{"class":34,"line":78},[32,337,338],{"class":38},"\u002F\u002F └────────────────────────────────────────────────────────────┘\n",[32,340,341],{"class":34,"line":84},[32,342,176],{"emptyLinePlaceholder":175},[32,344,345,347,350],{"class":34,"line":90},[32,346,183],{"class":182},[32,348,349],{"class":186}," basics",[32,351,191],{"class":190},[32,353,354,356,358,361,363,365,367,369,372,376,379,382,384,387,389,392],{"class":34,"line":96},[32,355,197],{"class":190},[32,357,200],{"class":182},[32,359,360],{"class":182}," map",[32,362,212],{"class":190},[32,364,215],{"class":182},[32,366,218],{"class":190},[32,368,221],{"class":182},[32,370,371],{"class":190},"{",[32,373,375],{"class":374},"sJ6F3","\"a\"",[32,377,378],{"class":190},": ",[32,380,381],{"class":227},"1",[32,383,224],{"class":190},[32,385,386],{"class":374},"\"b\"",[32,388,378],{"class":190},[32,390,391],{"class":227},"2",[32,393,287],{"class":190},[32,395,396,399,402,405,408],{"class":34,"line":102},[32,397,398],{"class":190},"    m[",[32,400,401],{"class":374},"\"c\"",[32,403,404],{"class":190},"] ",[32,406,407],{"class":182},"=",[32,409,410],{"class":227}," 3\n",[32,412,413,416,419,421],{"class":34,"line":108},[32,414,415],{"class":186},"    delete",[32,417,418],{"class":190},"(m, ",[32,420,375],{"class":374},[32,422,423],{"class":190},")\n",[32,425,426],{"class":34,"line":114},[32,427,176],{"emptyLinePlaceholder":175},[32,429,430],{"class":34,"line":120},[32,431,432],{"class":38},"    \u002F\u002F Comma-ok: distinguish \"absent\" from \"zero value\"\n",[32,434,435,438,440,443,446],{"class":34,"line":125},[32,436,437],{"class":190},"    v, ok ",[32,439,200],{"class":182},[32,441,442],{"class":190}," m[",[32,444,445],{"class":374},"\"x\"",[32,447,448],{"class":190},"]\n",[32,450,451,454,457],{"class":34,"line":131},[32,452,453],{"class":182},"    if",[32,455,456],{"class":182}," !",[32,458,459],{"class":190},"ok {\n",[32,461,462],{"class":34,"line":137},[32,463,464],{"class":38},"        \u002F\u002F \"x\" is not in the map\n",[32,466,467,470,473,475,478],{"class":34,"line":143},[32,468,469],{"class":190},"        fmt.",[32,471,472],{"class":186},"Println",[32,474,206],{"class":190},[32,476,477],{"class":374},"\"missing\"",[32,479,423],{"class":190},[32,481,482,485,488],{"class":34,"line":148},[32,483,484],{"class":190},"    } ",[32,486,487],{"class":182},"else",[32,489,490],{"class":190}," {\n",[32,492,493,495,497,499,502],{"class":34,"line":154},[32,494,469],{"class":190},[32,496,472],{"class":186},[32,498,206],{"class":190},[32,500,501],{"class":374},"\"value:\"",[32,503,504],{"class":190},", v)\n",[32,506,507],{"class":34,"line":160},[32,508,509],{"class":190},"    }\n",[32,511,512],{"class":34,"line":166},[32,513,176],{"emptyLinePlaceholder":175},[32,515,516],{"class":34,"line":172},[32,517,518],{"class":38},"    \u002F\u002F ⚠️ Without comma-ok, m[\"missing\"] returns the ZERO VALUE:\n",[32,520,521,524,526,529,532,535],{"class":34,"line":179},[32,522,523],{"class":190},"    fmt.",[32,525,472],{"class":186},[32,527,528],{"class":190},"(m[",[32,530,531],{"class":374},"\"nonexistent\"",[32,533,534],{"class":190},"])  ",[32,536,537],{"class":38},"\u002F\u002F 0 — indistinguishable from a stored 0\n",[32,539,540],{"class":34,"line":194},[32,541,176],{"emptyLinePlaceholder":175},[32,543,544],{"class":34,"line":237},[32,545,546],{"class":38},"    \u002F\u002F Reading a nil map is safe (returns zero value):\n",[32,548,549,552,555,557,559,561,563],{"class":34,"line":243},[32,550,551],{"class":182},"    var",[32,553,554],{"class":190}," nilMap ",[32,556,209],{"class":182},[32,558,212],{"class":190},[32,560,215],{"class":182},[32,562,218],{"class":190},[32,564,565],{"class":182},"int\n",[32,567,568,570,572,575,577,579],{"class":34,"line":249},[32,569,523],{"class":190},[32,571,472],{"class":186},[32,573,574],{"class":190},"(nilMap[",[32,576,375],{"class":374},[32,578,534],{"class":190},[32,580,581],{"class":38},"\u002F\u002F 0 — no panic\n",[32,583,584],{"class":34,"line":255},[32,585,176],{"emptyLinePlaceholder":175},[32,587,588],{"class":34,"line":260},[32,589,590],{"class":38},"    \u002F\u002F Writing to a nil map PANICS:\n",[32,592,593,596],{"class":34,"line":266},[32,594,595],{"class":38},"    \u002F\u002F nilMap[\"a\"] = 1",[32,597,598],{"class":38},"  \u002F\u002F panic: assignment to entry in nil map\n",[32,600,601],{"class":34,"line":272},[32,602,287],{"class":190},[14,604,606],{"id":605},"the-non-addressable-value-trap","The Non-Addressable Value Trap",[19,608,609,1067,1071],{"language":21},[23,610,612],{"className":25,"code":611,"language":21,"meta":27,"style":27},"type User struct{ Name string; Active bool }\n\nfunc mapFieldTrap() {\n    users := map[int]User{1: {\"Alice\", false}}\n\n    \u002F\u002F ❌ Compile error: cannot assign to struct field users[1].Active\n    \u002F\u002F users[1].Active = true\n    \u002F\u002F\n    \u002F\u002F WHY: map entries are NOT addressable — they can move during\n    \u002F\u002F rehashing. &users[1] would be a dangling pointer after a growth.\n\n    \u002F\u002F ✅ Fix 1: copy out, modify, assign back:\n    u := users[1]\n    u.Active = true\n    users[1] = u\n\n    \u002F\u002F ✅ Fix 2: store pointers (the struct lives on the heap, the map\n    \u002F\u002F    holds pointers — pointers are addressable):\n    usersPtr := map[int]*User{1: {\"Alice\", false}}\n    usersPtr[1].Active = true  \u002F\u002F ✅ usersPtr[1] is *User, modifiable\n    \u002F\u002F Trade-off: extra allocation per struct, must nil-check pointers\n}\n\n\u002F\u002F ✅ Production pattern: map of pointers for mutable structs:\ntype Session struct {\n    ID     string\n    UserID int64\n    Expiry time.Time\n}\n\ntype SessionStore struct {\n    mu       sync.RWMutex\n    sessions map[string]*Session  \u002F\u002F pointers — fields modifiable in place\n}\n\nfunc (s *SessionStore) Touch(id string) {\n    s.mu.Lock()\n    defer s.mu.Unlock()\n    if sess, ok := s.sessions[id]; ok {  \u002F\u002F nil-check the pointer\n        sess.Expiry = time.Now().Add(30 * time.Minute)\n    }\n}\n",[29,613,614,639,643,652,688,692,697,702,707,712,717,721,726,740,750,764,768,773,778,812,830,835,839,843,848,859,867,875,889,893,897,908,921,942,946,950,984,996,1010,1026,1057,1062],{"__ignoreMap":27},[32,615,616,619,622,625,628,630,633,636],{"class":34,"line":35},[32,617,618],{"class":182},"type",[32,620,621],{"class":186}," User",[32,623,624],{"class":182}," struct",[32,626,627],{"class":190},"{ Name ",[32,629,215],{"class":182},[32,631,632],{"class":190},"; Active ",[32,634,635],{"class":182},"bool",[32,637,638],{"class":190}," }\n",[32,640,641],{"class":34,"line":42},[32,642,176],{"emptyLinePlaceholder":175},[32,644,645,647,650],{"class":34,"line":48},[32,646,183],{"class":182},[32,648,649],{"class":186}," mapFieldTrap",[32,651,191],{"class":190},[32,653,654,657,659,661,663,665,667,670,672,674,677,680,682,685],{"class":34,"line":54},[32,655,656],{"class":190},"    users ",[32,658,200],{"class":182},[32,660,360],{"class":182},[32,662,212],{"class":190},[32,664,221],{"class":182},[32,666,218],{"class":190},[32,668,669],{"class":186},"User",[32,671,371],{"class":190},[32,673,381],{"class":227},[32,675,676],{"class":190},": {",[32,678,679],{"class":374},"\"Alice\"",[32,681,224],{"class":190},[32,683,684],{"class":227},"false",[32,686,687],{"class":190},"}}\n",[32,689,690],{"class":34,"line":60},[32,691,176],{"emptyLinePlaceholder":175},[32,693,694],{"class":34,"line":66},[32,695,696],{"class":38},"    \u002F\u002F ❌ Compile error: cannot assign to struct field users[1].Active\n",[32,698,699],{"class":34,"line":72},[32,700,701],{"class":38},"    \u002F\u002F users[1].Active = true\n",[32,703,704],{"class":34,"line":78},[32,705,706],{"class":38},"    \u002F\u002F\n",[32,708,709],{"class":34,"line":84},[32,710,711],{"class":38},"    \u002F\u002F WHY: map entries are NOT addressable — they can move during\n",[32,713,714],{"class":34,"line":90},[32,715,716],{"class":38},"    \u002F\u002F rehashing. &users[1] would be a dangling pointer after a growth.\n",[32,718,719],{"class":34,"line":96},[32,720,176],{"emptyLinePlaceholder":175},[32,722,723],{"class":34,"line":102},[32,724,725],{"class":38},"    \u002F\u002F ✅ Fix 1: copy out, modify, assign back:\n",[32,727,728,731,733,736,738],{"class":34,"line":108},[32,729,730],{"class":190},"    u ",[32,732,200],{"class":182},[32,734,735],{"class":190}," users[",[32,737,381],{"class":227},[32,739,448],{"class":190},[32,741,742,745,747],{"class":34,"line":114},[32,743,744],{"class":190},"    u.Active ",[32,746,407],{"class":182},[32,748,749],{"class":227}," true\n",[32,751,752,755,757,759,761],{"class":34,"line":120},[32,753,754],{"class":190},"    users[",[32,756,381],{"class":227},[32,758,404],{"class":190},[32,760,407],{"class":182},[32,762,763],{"class":190}," u\n",[32,765,766],{"class":34,"line":125},[32,767,176],{"emptyLinePlaceholder":175},[32,769,770],{"class":34,"line":131},[32,771,772],{"class":38},"    \u002F\u002F ✅ Fix 2: store pointers (the struct lives on the heap, the map\n",[32,774,775],{"class":34,"line":137},[32,776,777],{"class":38},"    \u002F\u002F    holds pointers — pointers are addressable):\n",[32,779,780,783,785,787,789,791,793,796,798,800,802,804,806,808,810],{"class":34,"line":143},[32,781,782],{"class":190},"    usersPtr ",[32,784,200],{"class":182},[32,786,360],{"class":182},[32,788,212],{"class":190},[32,790,221],{"class":182},[32,792,218],{"class":190},[32,794,795],{"class":182},"*",[32,797,669],{"class":186},[32,799,371],{"class":190},[32,801,381],{"class":227},[32,803,676],{"class":190},[32,805,679],{"class":374},[32,807,224],{"class":190},[32,809,684],{"class":227},[32,811,687],{"class":190},[32,813,814,817,819,822,824,827],{"class":34,"line":148},[32,815,816],{"class":190},"    usersPtr[",[32,818,381],{"class":227},[32,820,821],{"class":190},"].Active ",[32,823,407],{"class":182},[32,825,826],{"class":227}," true",[32,828,829],{"class":38},"  \u002F\u002F ✅ usersPtr[1] is *User, modifiable\n",[32,831,832],{"class":34,"line":154},[32,833,834],{"class":38},"    \u002F\u002F Trade-off: extra allocation per struct, must nil-check pointers\n",[32,836,837],{"class":34,"line":160},[32,838,287],{"class":190},[32,840,841],{"class":34,"line":166},[32,842,176],{"emptyLinePlaceholder":175},[32,844,845],{"class":34,"line":172},[32,846,847],{"class":38},"\u002F\u002F ✅ Production pattern: map of pointers for mutable structs:\n",[32,849,850,852,855,857],{"class":34,"line":179},[32,851,618],{"class":182},[32,853,854],{"class":186}," Session",[32,856,624],{"class":182},[32,858,490],{"class":190},[32,860,861,864],{"class":34,"line":194},[32,862,863],{"class":190},"    ID     ",[32,865,866],{"class":182},"string\n",[32,868,869,872],{"class":34,"line":237},[32,870,871],{"class":190},"    UserID ",[32,873,874],{"class":182},"int64\n",[32,876,877,880,883,886],{"class":34,"line":243},[32,878,879],{"class":190},"    Expiry ",[32,881,882],{"class":186},"time",[32,884,885],{"class":190},".",[32,887,888],{"class":186},"Time\n",[32,890,891],{"class":34,"line":249},[32,892,287],{"class":190},[32,894,895],{"class":34,"line":255},[32,896,176],{"emptyLinePlaceholder":175},[32,898,899,901,904,906],{"class":34,"line":260},[32,900,618],{"class":182},[32,902,903],{"class":186}," SessionStore",[32,905,624],{"class":182},[32,907,490],{"class":190},[32,909,910,913,916,918],{"class":34,"line":266},[32,911,912],{"class":190},"    mu       ",[32,914,915],{"class":186},"sync",[32,917,885],{"class":190},[32,919,920],{"class":186},"RWMutex\n",[32,922,923,926,928,930,932,934,936,939],{"class":34,"line":272},[32,924,925],{"class":190},"    sessions ",[32,927,209],{"class":182},[32,929,212],{"class":190},[32,931,215],{"class":182},[32,933,218],{"class":190},[32,935,795],{"class":182},[32,937,938],{"class":186},"Session",[32,940,941],{"class":38},"  \u002F\u002F pointers — fields modifiable in place\n",[32,943,944],{"class":34,"line":278},[32,945,287],{"class":190},[32,947,948],{"class":34,"line":284},[32,949,176],{"emptyLinePlaceholder":175},[32,951,953,955,958,962,964,967,970,973,975,978,981],{"class":34,"line":952},36,[32,954,183],{"class":182},[32,956,957],{"class":190}," (",[32,959,961],{"class":960},"sCrzJ","s ",[32,963,795],{"class":182},[32,965,966],{"class":186},"SessionStore",[32,968,969],{"class":190},") ",[32,971,972],{"class":186},"Touch",[32,974,206],{"class":190},[32,976,977],{"class":960},"id",[32,979,980],{"class":182}," string",[32,982,983],{"class":190},") {\n",[32,985,987,990,993],{"class":34,"line":986},37,[32,988,989],{"class":190},"    s.mu.",[32,991,992],{"class":186},"Lock",[32,994,995],{"class":190},"()\n",[32,997,999,1002,1005,1008],{"class":34,"line":998},38,[32,1000,1001],{"class":182},"    defer",[32,1003,1004],{"class":190}," s.mu.",[32,1006,1007],{"class":186},"Unlock",[32,1009,995],{"class":190},[32,1011,1013,1015,1018,1020,1023],{"class":34,"line":1012},39,[32,1014,453],{"class":182},[32,1016,1017],{"class":190}," sess, ok ",[32,1019,200],{"class":182},[32,1021,1022],{"class":190}," s.sessions[id]; ok {  ",[32,1024,1025],{"class":38},"\u002F\u002F nil-check the pointer\n",[32,1027,1029,1032,1034,1037,1040,1043,1046,1048,1051,1054],{"class":34,"line":1028},40,[32,1030,1031],{"class":190},"        sess.Expiry ",[32,1033,407],{"class":182},[32,1035,1036],{"class":190}," time.",[32,1038,1039],{"class":186},"Now",[32,1041,1042],{"class":190},"().",[32,1044,1045],{"class":186},"Add",[32,1047,206],{"class":190},[32,1049,1050],{"class":227},"30",[32,1052,1053],{"class":182}," *",[32,1055,1056],{"class":190}," time.Minute)\n",[32,1058,1060],{"class":34,"line":1059},41,[32,1061,509],{"class":190},[32,1063,1065],{"class":34,"line":1064},42,[32,1066,287],{"class":190},[14,1068,1070],{"id":1069},"concurrent-map-access-the-fatal-error","Concurrent Map Access — The Fatal Error",[19,1072,1073,1732,1736],{"language":21},[23,1074,1076],{"className":25,"code":1075,"language":21,"meta":27,"style":27},"\u002F\u002F ❌ ANTI-PATTERN: concurrent map writes — FATAL (not recoverable)\nfunc concurrentMapBad() {\n    m := map[int]int{}\n    go func() { m[1] = 1 }()\n    go func() { m[2] = 2 }()\n    \u002F\u002F fatal error: concurrent map writes\n    \u002F\u002F The runtime detects this and aborts — you CANNOT recover.\n    \u002F\u002F This is not a panic; it's a direct crash.\n    time.Sleep(time.Second)\n}\n\n\u002F\u002F ✅ Pattern 1: sync.RWMutex + map (general purpose, type-safe)\ntype SafeMap[K comparable, V any] struct {\n    mu sync.RWMutex\n    m  map[K]V\n}\n\nfunc NewSafeMap[K comparable, V any]() *SafeMap[K, V] {\n    return &SafeMap[K, V]{m: make(map[K]V)}\n}\n\nfunc (sm *SafeMap[K, V]) Get(key K) (V, bool) {\n    sm.mu.RLock()\n    defer sm.mu.RUnlock()\n    v, ok := sm.m[key]\n    return v, ok\n}\n\nfunc (sm *SafeMap[K, V]) Set(key K, val V) {\n    sm.mu.Lock()\n    defer sm.mu.Unlock()\n    sm.m[key] = val\n}\n\nfunc (sm *SafeMap[K, V]) Delete(key K) {\n    sm.mu.Lock()\n    defer sm.mu.Unlock()\n    delete(sm.m, key)\n}\n\n\u002F\u002F ✅ Pattern 2: sync.Map (write-rarely, read-many)\n\u002F\u002F import \"sync\"\nvar cache sync.Map\ncache.Store(\"key\", \"value\")\nv, ok := cache.Load(\"key\")\ncache.Delete(\"key\")\ncache.Range(func(k, v any) bool {\n    return true  \u002F\u002F continue iteration\n})\n\u002F\u002F Trade-off: uses `any` (no generics — must type-assert), slower than\n\u002F\u002F map+RWMutex for balanced read\u002Fwrite, but faster for write-rarely.\n\n\u002F\u002F ✅ Pattern 3: channel-owned map (owner goroutine pattern)\n\u002F\u002F See chapter 26 — one goroutine owns the map, others send commands.\n",[29,1077,1078,1083,1092,1111,1134,1153,1158,1163,1168,1179,1183,1187,1192,1222,1233,1249,1253,1257,1295,1334,1338,1342,1388,1398,1410,1419,1426,1430,1434,1475,1483,1493,1503,1507,1511,1544,1552,1562,1569,1573,1577,1582,1587,1603,1624,1644,1657,1687,1697,1703,1709,1715,1720,1726],{"__ignoreMap":27},[32,1079,1080],{"class":34,"line":35},[32,1081,1082],{"class":38},"\u002F\u002F ❌ ANTI-PATTERN: concurrent map writes — FATAL (not recoverable)\n",[32,1084,1085,1087,1090],{"class":34,"line":42},[32,1086,183],{"class":182},[32,1088,1089],{"class":186}," concurrentMapBad",[32,1091,191],{"class":190},[32,1093,1094,1096,1098,1100,1102,1104,1106,1108],{"class":34,"line":48},[32,1095,197],{"class":190},[32,1097,200],{"class":182},[32,1099,360],{"class":182},[32,1101,212],{"class":190},[32,1103,221],{"class":182},[32,1105,218],{"class":190},[32,1107,221],{"class":182},[32,1109,1110],{"class":190},"{}\n",[32,1112,1113,1116,1119,1122,1124,1126,1128,1131],{"class":34,"line":54},[32,1114,1115],{"class":182},"    go",[32,1117,1118],{"class":182}," func",[32,1120,1121],{"class":190},"() { m[",[32,1123,381],{"class":227},[32,1125,404],{"class":190},[32,1127,407],{"class":182},[32,1129,1130],{"class":227}," 1",[32,1132,1133],{"class":190}," }()\n",[32,1135,1136,1138,1140,1142,1144,1146,1148,1151],{"class":34,"line":60},[32,1137,1115],{"class":182},[32,1139,1118],{"class":182},[32,1141,1121],{"class":190},[32,1143,391],{"class":227},[32,1145,404],{"class":190},[32,1147,407],{"class":182},[32,1149,1150],{"class":227}," 2",[32,1152,1133],{"class":190},[32,1154,1155],{"class":34,"line":66},[32,1156,1157],{"class":38},"    \u002F\u002F fatal error: concurrent map writes\n",[32,1159,1160],{"class":34,"line":72},[32,1161,1162],{"class":38},"    \u002F\u002F The runtime detects this and aborts — you CANNOT recover.\n",[32,1164,1165],{"class":34,"line":78},[32,1166,1167],{"class":38},"    \u002F\u002F This is not a panic; it's a direct crash.\n",[32,1169,1170,1173,1176],{"class":34,"line":84},[32,1171,1172],{"class":190},"    time.",[32,1174,1175],{"class":186},"Sleep",[32,1177,1178],{"class":190},"(time.Second)\n",[32,1180,1181],{"class":34,"line":90},[32,1182,287],{"class":190},[32,1184,1185],{"class":34,"line":96},[32,1186,176],{"emptyLinePlaceholder":175},[32,1188,1189],{"class":34,"line":102},[32,1190,1191],{"class":38},"\u002F\u002F ✅ Pattern 1: sync.RWMutex + map (general purpose, type-safe)\n",[32,1193,1194,1196,1199,1201,1204,1207,1209,1212,1215,1217,1220],{"class":34,"line":108},[32,1195,618],{"class":182},[32,1197,1198],{"class":186}," SafeMap",[32,1200,212],{"class":190},[32,1202,1203],{"class":960},"K",[32,1205,1206],{"class":186}," comparable",[32,1208,224],{"class":190},[32,1210,1211],{"class":960},"V",[32,1213,1214],{"class":186}," any",[32,1216,404],{"class":190},[32,1218,1219],{"class":182},"struct",[32,1221,490],{"class":190},[32,1223,1224,1227,1229,1231],{"class":34,"line":114},[32,1225,1226],{"class":190},"    mu ",[32,1228,915],{"class":186},[32,1230,885],{"class":190},[32,1232,920],{"class":186},[32,1234,1235,1238,1240,1242,1244,1246],{"class":34,"line":120},[32,1236,1237],{"class":190},"    m  ",[32,1239,209],{"class":182},[32,1241,212],{"class":190},[32,1243,1203],{"class":186},[32,1245,218],{"class":190},[32,1247,1248],{"class":186},"V\n",[32,1250,1251],{"class":34,"line":125},[32,1252,287],{"class":190},[32,1254,1255],{"class":34,"line":131},[32,1256,176],{"emptyLinePlaceholder":175},[32,1258,1259,1261,1264,1266,1268,1270,1272,1274,1276,1279,1281,1284,1286,1288,1290,1292],{"class":34,"line":137},[32,1260,183],{"class":182},[32,1262,1263],{"class":186}," NewSafeMap",[32,1265,212],{"class":190},[32,1267,1203],{"class":960},[32,1269,1206],{"class":186},[32,1271,224],{"class":190},[32,1273,1211],{"class":960},[32,1275,1214],{"class":186},[32,1277,1278],{"class":190},"]() ",[32,1280,795],{"class":182},[32,1282,1283],{"class":186},"SafeMap",[32,1285,212],{"class":190},[32,1287,1203],{"class":186},[32,1289,224],{"class":190},[32,1291,1211],{"class":186},[32,1293,1294],{"class":190},"] {\n",[32,1296,1297,1300,1303,1305,1307,1309,1311,1313,1316,1319,1321,1323,1325,1327,1329,1331],{"class":34,"line":143},[32,1298,1299],{"class":182},"    return",[32,1301,1302],{"class":182}," &",[32,1304,1283],{"class":186},[32,1306,212],{"class":190},[32,1308,1203],{"class":186},[32,1310,224],{"class":190},[32,1312,1211],{"class":186},[32,1314,1315],{"class":190},"]{m: ",[32,1317,1318],{"class":186},"make",[32,1320,206],{"class":190},[32,1322,209],{"class":182},[32,1324,212],{"class":190},[32,1326,1203],{"class":186},[32,1328,218],{"class":190},[32,1330,1211],{"class":186},[32,1332,1333],{"class":190},")}\n",[32,1335,1336],{"class":34,"line":148},[32,1337,287],{"class":190},[32,1339,1340],{"class":34,"line":154},[32,1341,176],{"emptyLinePlaceholder":175},[32,1343,1344,1346,1348,1351,1353,1355,1357,1359,1361,1363,1366,1369,1371,1374,1377,1380,1382,1384,1386],{"class":34,"line":160},[32,1345,183],{"class":182},[32,1347,957],{"class":190},[32,1349,1350],{"class":960},"sm ",[32,1352,795],{"class":182},[32,1354,1283],{"class":186},[32,1356,212],{"class":190},[32,1358,1203],{"class":186},[32,1360,224],{"class":190},[32,1362,1211],{"class":186},[32,1364,1365],{"class":190},"]) ",[32,1367,1368],{"class":186},"Get",[32,1370,206],{"class":190},[32,1372,1373],{"class":960},"key",[32,1375,1376],{"class":186}," K",[32,1378,1379],{"class":190},") (",[32,1381,1211],{"class":186},[32,1383,224],{"class":190},[32,1385,635],{"class":182},[32,1387,983],{"class":190},[32,1389,1390,1393,1396],{"class":34,"line":166},[32,1391,1392],{"class":190},"    sm.mu.",[32,1394,1395],{"class":186},"RLock",[32,1397,995],{"class":190},[32,1399,1400,1402,1405,1408],{"class":34,"line":172},[32,1401,1001],{"class":182},[32,1403,1404],{"class":190}," sm.mu.",[32,1406,1407],{"class":186},"RUnlock",[32,1409,995],{"class":190},[32,1411,1412,1414,1416],{"class":34,"line":179},[32,1413,437],{"class":190},[32,1415,200],{"class":182},[32,1417,1418],{"class":190}," sm.m[key]\n",[32,1420,1421,1423],{"class":34,"line":194},[32,1422,1299],{"class":182},[32,1424,1425],{"class":190}," v, ok\n",[32,1427,1428],{"class":34,"line":237},[32,1429,287],{"class":190},[32,1431,1432],{"class":34,"line":243},[32,1433,176],{"emptyLinePlaceholder":175},[32,1435,1436,1438,1440,1442,1444,1446,1448,1450,1452,1454,1456,1459,1461,1463,1465,1467,1470,1473],{"class":34,"line":249},[32,1437,183],{"class":182},[32,1439,957],{"class":190},[32,1441,1350],{"class":960},[32,1443,795],{"class":182},[32,1445,1283],{"class":186},[32,1447,212],{"class":190},[32,1449,1203],{"class":186},[32,1451,224],{"class":190},[32,1453,1211],{"class":186},[32,1455,1365],{"class":190},[32,1457,1458],{"class":186},"Set",[32,1460,206],{"class":190},[32,1462,1373],{"class":960},[32,1464,1376],{"class":186},[32,1466,224],{"class":190},[32,1468,1469],{"class":960},"val",[32,1471,1472],{"class":186}," V",[32,1474,983],{"class":190},[32,1476,1477,1479,1481],{"class":34,"line":255},[32,1478,1392],{"class":190},[32,1480,992],{"class":186},[32,1482,995],{"class":190},[32,1484,1485,1487,1489,1491],{"class":34,"line":260},[32,1486,1001],{"class":182},[32,1488,1404],{"class":190},[32,1490,1007],{"class":186},[32,1492,995],{"class":190},[32,1494,1495,1498,1500],{"class":34,"line":266},[32,1496,1497],{"class":190},"    sm.m[key] ",[32,1499,407],{"class":182},[32,1501,1502],{"class":190}," val\n",[32,1504,1505],{"class":34,"line":272},[32,1506,287],{"class":190},[32,1508,1509],{"class":34,"line":278},[32,1510,176],{"emptyLinePlaceholder":175},[32,1512,1513,1515,1517,1519,1521,1523,1525,1527,1529,1531,1533,1536,1538,1540,1542],{"class":34,"line":284},[32,1514,183],{"class":182},[32,1516,957],{"class":190},[32,1518,1350],{"class":960},[32,1520,795],{"class":182},[32,1522,1283],{"class":186},[32,1524,212],{"class":190},[32,1526,1203],{"class":186},[32,1528,224],{"class":190},[32,1530,1211],{"class":186},[32,1532,1365],{"class":190},[32,1534,1535],{"class":186},"Delete",[32,1537,206],{"class":190},[32,1539,1373],{"class":960},[32,1541,1376],{"class":186},[32,1543,983],{"class":190},[32,1545,1546,1548,1550],{"class":34,"line":952},[32,1547,1392],{"class":190},[32,1549,992],{"class":186},[32,1551,995],{"class":190},[32,1553,1554,1556,1558,1560],{"class":34,"line":986},[32,1555,1001],{"class":182},[32,1557,1404],{"class":190},[32,1559,1007],{"class":186},[32,1561,995],{"class":190},[32,1563,1564,1566],{"class":34,"line":998},[32,1565,415],{"class":186},[32,1567,1568],{"class":190},"(sm.m, key)\n",[32,1570,1571],{"class":34,"line":1012},[32,1572,287],{"class":190},[32,1574,1575],{"class":34,"line":1028},[32,1576,176],{"emptyLinePlaceholder":175},[32,1578,1579],{"class":34,"line":1059},[32,1580,1581],{"class":38},"\u002F\u002F ✅ Pattern 2: sync.Map (write-rarely, read-many)\n",[32,1583,1584],{"class":34,"line":1064},[32,1585,1586],{"class":38},"\u002F\u002F import \"sync\"\n",[32,1588,1590,1593,1596,1598,1600],{"class":34,"line":1589},43,[32,1591,1592],{"class":182},"var",[32,1594,1595],{"class":190}," cache ",[32,1597,915],{"class":186},[32,1599,885],{"class":190},[32,1601,1602],{"class":186},"Map\n",[32,1604,1606,1609,1612,1614,1617,1619,1622],{"class":34,"line":1605},44,[32,1607,1608],{"class":190},"cache.",[32,1610,1611],{"class":186},"Store",[32,1613,206],{"class":190},[32,1615,1616],{"class":374},"\"key\"",[32,1618,224],{"class":190},[32,1620,1621],{"class":374},"\"value\"",[32,1623,423],{"class":190},[32,1625,1627,1630,1632,1635,1638,1640,1642],{"class":34,"line":1626},45,[32,1628,1629],{"class":190},"v, ok ",[32,1631,200],{"class":182},[32,1633,1634],{"class":190}," cache.",[32,1636,1637],{"class":186},"Load",[32,1639,206],{"class":190},[32,1641,1616],{"class":374},[32,1643,423],{"class":190},[32,1645,1647,1649,1651,1653,1655],{"class":34,"line":1646},46,[32,1648,1608],{"class":190},[32,1650,1535],{"class":186},[32,1652,206],{"class":190},[32,1654,1616],{"class":374},[32,1656,423],{"class":190},[32,1658,1660,1662,1665,1667,1669,1671,1674,1676,1679,1681,1683,1685],{"class":34,"line":1659},47,[32,1661,1608],{"class":190},[32,1663,1664],{"class":186},"Range",[32,1666,206],{"class":190},[32,1668,183],{"class":182},[32,1670,206],{"class":190},[32,1672,1673],{"class":960},"k",[32,1675,224],{"class":190},[32,1677,1678],{"class":960},"v",[32,1680,1214],{"class":186},[32,1682,969],{"class":190},[32,1684,635],{"class":182},[32,1686,490],{"class":190},[32,1688,1690,1692,1694],{"class":34,"line":1689},48,[32,1691,1299],{"class":182},[32,1693,826],{"class":227},[32,1695,1696],{"class":38},"  \u002F\u002F continue iteration\n",[32,1698,1700],{"class":34,"line":1699},49,[32,1701,1702],{"class":190},"})\n",[32,1704,1706],{"class":34,"line":1705},50,[32,1707,1708],{"class":38},"\u002F\u002F Trade-off: uses `any` (no generics — must type-assert), slower than\n",[32,1710,1712],{"class":34,"line":1711},51,[32,1713,1714],{"class":38},"\u002F\u002F map+RWMutex for balanced read\u002Fwrite, but faster for write-rarely.\n",[32,1716,1718],{"class":34,"line":1717},52,[32,1719,176],{"emptyLinePlaceholder":175},[32,1721,1723],{"class":34,"line":1722},53,[32,1724,1725],{"class":38},"\u002F\u002F ✅ Pattern 3: channel-owned map (owner goroutine pattern)\n",[32,1727,1729],{"class":34,"line":1728},54,[32,1730,1731],{"class":38},"\u002F\u002F See chapter 26 — one goroutine owns the map, others send commands.\n",[14,1733,1735],{"id":1734},"ordered-map-production-implementation","Ordered Map — Production Implementation",[19,1737,1738,2283,2287],{"language":21},[23,1739,1741],{"className":25,"code":1740,"language":21,"meta":27,"style":27},"\u002F\u002F Go's map is unordered (intentionally randomized). When you need\n\u002F\u002F insertion-order iteration, build an ordered map:\n\ntype OrderedMap[K comparable, V any] struct {\n    keys []K          \u002F\u002F insertion order\n    data map[K]V      \u002F\u002F fast lookup\n}\n\nfunc NewOrderedMap[K comparable, V any]() *OrderedMap[K, V] {\n    return &OrderedMap[K, V]{data: make(map[K]V)}\n}\n\nfunc (m *OrderedMap[K, V]) Set(key K, val V) {\n    if _, exists := m.data[key]; !exists {\n        m.keys = append(m.keys, key)  \u002F\u002F only add to keys on first insertion\n    }\n    m.data[key] = val\n}\n\nfunc (m *OrderedMap[K, V]) Get(key K) (V, bool) {\n    v, ok := m.data[key]\n    return v, ok\n}\n\nfunc (m *OrderedMap[K, V]) Delete(key K) {\n    if _, exists := m.data[key]; !exists {\n        return\n    }\n    delete(m.data, key)\n    \u002F\u002F Remove from keys slice (O(n) — use a linked list for O(1) deletion):\n    for i, k := range m.keys {\n        if k == key {\n            m.keys = append(m.keys[:i], m.keys[i+1:]...)\n            break\n        }\n    }\n}\n\nfunc (m *OrderedMap[K, V]) Range(fn func(K, V) bool) {\n    for _, k := range m.keys {\n        if !fn(k, m.data[k]) {\n            break\n        }\n    }\n}\n",[29,1742,1743,1748,1753,1757,1782,1792,1810,1814,1818,1854,1889,1893,1897,1936,1954,1970,1974,1983,1987,1991,2031,2040,2046,2050,2054,2086,2100,2105,2109,2116,2121,2137,2151,2176,2181,2186,2190,2194,2198,2243,2256,2267,2271,2275,2279],{"__ignoreMap":27},[32,1744,1745],{"class":34,"line":35},[32,1746,1747],{"class":38},"\u002F\u002F Go's map is unordered (intentionally randomized). When you need\n",[32,1749,1750],{"class":34,"line":42},[32,1751,1752],{"class":38},"\u002F\u002F insertion-order iteration, build an ordered map:\n",[32,1754,1755],{"class":34,"line":48},[32,1756,176],{"emptyLinePlaceholder":175},[32,1758,1759,1761,1764,1766,1768,1770,1772,1774,1776,1778,1780],{"class":34,"line":54},[32,1760,618],{"class":182},[32,1762,1763],{"class":186}," OrderedMap",[32,1765,212],{"class":190},[32,1767,1203],{"class":960},[32,1769,1206],{"class":186},[32,1771,224],{"class":190},[32,1773,1211],{"class":960},[32,1775,1214],{"class":186},[32,1777,404],{"class":190},[32,1779,1219],{"class":182},[32,1781,490],{"class":190},[32,1783,1784,1787,1789],{"class":34,"line":60},[32,1785,1786],{"class":190},"    keys []",[32,1788,1203],{"class":186},[32,1790,1791],{"class":38},"          \u002F\u002F insertion order\n",[32,1793,1794,1797,1799,1801,1803,1805,1807],{"class":34,"line":66},[32,1795,1796],{"class":190},"    data ",[32,1798,209],{"class":182},[32,1800,212],{"class":190},[32,1802,1203],{"class":186},[32,1804,218],{"class":190},[32,1806,1211],{"class":186},[32,1808,1809],{"class":38},"      \u002F\u002F fast lookup\n",[32,1811,1812],{"class":34,"line":72},[32,1813,287],{"class":190},[32,1815,1816],{"class":34,"line":78},[32,1817,176],{"emptyLinePlaceholder":175},[32,1819,1820,1822,1825,1827,1829,1831,1833,1835,1837,1839,1841,1844,1846,1848,1850,1852],{"class":34,"line":84},[32,1821,183],{"class":182},[32,1823,1824],{"class":186}," NewOrderedMap",[32,1826,212],{"class":190},[32,1828,1203],{"class":960},[32,1830,1206],{"class":186},[32,1832,224],{"class":190},[32,1834,1211],{"class":960},[32,1836,1214],{"class":186},[32,1838,1278],{"class":190},[32,1840,795],{"class":182},[32,1842,1843],{"class":186},"OrderedMap",[32,1845,212],{"class":190},[32,1847,1203],{"class":186},[32,1849,224],{"class":190},[32,1851,1211],{"class":186},[32,1853,1294],{"class":190},[32,1855,1856,1858,1860,1862,1864,1866,1868,1870,1873,1875,1877,1879,1881,1883,1885,1887],{"class":34,"line":90},[32,1857,1299],{"class":182},[32,1859,1302],{"class":182},[32,1861,1843],{"class":186},[32,1863,212],{"class":190},[32,1865,1203],{"class":186},[32,1867,224],{"class":190},[32,1869,1211],{"class":186},[32,1871,1872],{"class":190},"]{data: ",[32,1874,1318],{"class":186},[32,1876,206],{"class":190},[32,1878,209],{"class":182},[32,1880,212],{"class":190},[32,1882,1203],{"class":186},[32,1884,218],{"class":190},[32,1886,1211],{"class":186},[32,1888,1333],{"class":190},[32,1890,1891],{"class":34,"line":96},[32,1892,287],{"class":190},[32,1894,1895],{"class":34,"line":102},[32,1896,176],{"emptyLinePlaceholder":175},[32,1898,1899,1901,1903,1906,1908,1910,1912,1914,1916,1918,1920,1922,1924,1926,1928,1930,1932,1934],{"class":34,"line":108},[32,1900,183],{"class":182},[32,1902,957],{"class":190},[32,1904,1905],{"class":960},"m ",[32,1907,795],{"class":182},[32,1909,1843],{"class":186},[32,1911,212],{"class":190},[32,1913,1203],{"class":186},[32,1915,224],{"class":190},[32,1917,1211],{"class":186},[32,1919,1365],{"class":190},[32,1921,1458],{"class":186},[32,1923,206],{"class":190},[32,1925,1373],{"class":960},[32,1927,1376],{"class":186},[32,1929,224],{"class":190},[32,1931,1469],{"class":960},[32,1933,1472],{"class":186},[32,1935,983],{"class":190},[32,1937,1938,1940,1943,1945,1948,1951],{"class":34,"line":114},[32,1939,453],{"class":182},[32,1941,1942],{"class":190}," _, exists ",[32,1944,200],{"class":182},[32,1946,1947],{"class":190}," m.data[key]; ",[32,1949,1950],{"class":182},"!",[32,1952,1953],{"class":190},"exists {\n",[32,1955,1956,1959,1961,1964,1967],{"class":34,"line":120},[32,1957,1958],{"class":190},"        m.keys ",[32,1960,407],{"class":182},[32,1962,1963],{"class":186}," append",[32,1965,1966],{"class":190},"(m.keys, key)  ",[32,1968,1969],{"class":38},"\u002F\u002F only add to keys on first insertion\n",[32,1971,1972],{"class":34,"line":125},[32,1973,509],{"class":190},[32,1975,1976,1979,1981],{"class":34,"line":131},[32,1977,1978],{"class":190},"    m.data[key] ",[32,1980,407],{"class":182},[32,1982,1502],{"class":190},[32,1984,1985],{"class":34,"line":137},[32,1986,287],{"class":190},[32,1988,1989],{"class":34,"line":143},[32,1990,176],{"emptyLinePlaceholder":175},[32,1992,1993,1995,1997,1999,2001,2003,2005,2007,2009,2011,2013,2015,2017,2019,2021,2023,2025,2027,2029],{"class":34,"line":148},[32,1994,183],{"class":182},[32,1996,957],{"class":190},[32,1998,1905],{"class":960},[32,2000,795],{"class":182},[32,2002,1843],{"class":186},[32,2004,212],{"class":190},[32,2006,1203],{"class":186},[32,2008,224],{"class":190},[32,2010,1211],{"class":186},[32,2012,1365],{"class":190},[32,2014,1368],{"class":186},[32,2016,206],{"class":190},[32,2018,1373],{"class":960},[32,2020,1376],{"class":186},[32,2022,1379],{"class":190},[32,2024,1211],{"class":186},[32,2026,224],{"class":190},[32,2028,635],{"class":182},[32,2030,983],{"class":190},[32,2032,2033,2035,2037],{"class":34,"line":154},[32,2034,437],{"class":190},[32,2036,200],{"class":182},[32,2038,2039],{"class":190}," m.data[key]\n",[32,2041,2042,2044],{"class":34,"line":160},[32,2043,1299],{"class":182},[32,2045,1425],{"class":190},[32,2047,2048],{"class":34,"line":166},[32,2049,287],{"class":190},[32,2051,2052],{"class":34,"line":172},[32,2053,176],{"emptyLinePlaceholder":175},[32,2055,2056,2058,2060,2062,2064,2066,2068,2070,2072,2074,2076,2078,2080,2082,2084],{"class":34,"line":179},[32,2057,183],{"class":182},[32,2059,957],{"class":190},[32,2061,1905],{"class":960},[32,2063,795],{"class":182},[32,2065,1843],{"class":186},[32,2067,212],{"class":190},[32,2069,1203],{"class":186},[32,2071,224],{"class":190},[32,2073,1211],{"class":186},[32,2075,1365],{"class":190},[32,2077,1535],{"class":186},[32,2079,206],{"class":190},[32,2081,1373],{"class":960},[32,2083,1376],{"class":186},[32,2085,983],{"class":190},[32,2087,2088,2090,2092,2094,2096,2098],{"class":34,"line":194},[32,2089,453],{"class":182},[32,2091,1942],{"class":190},[32,2093,200],{"class":182},[32,2095,1947],{"class":190},[32,2097,1950],{"class":182},[32,2099,1953],{"class":190},[32,2101,2102],{"class":34,"line":237},[32,2103,2104],{"class":182},"        return\n",[32,2106,2107],{"class":34,"line":243},[32,2108,509],{"class":190},[32,2110,2111,2113],{"class":34,"line":249},[32,2112,415],{"class":186},[32,2114,2115],{"class":190},"(m.data, key)\n",[32,2117,2118],{"class":34,"line":255},[32,2119,2120],{"class":38},"    \u002F\u002F Remove from keys slice (O(n) — use a linked list for O(1) deletion):\n",[32,2122,2123,2126,2129,2131,2134],{"class":34,"line":260},[32,2124,2125],{"class":182},"    for",[32,2127,2128],{"class":190}," i, k ",[32,2130,200],{"class":182},[32,2132,2133],{"class":182}," range",[32,2135,2136],{"class":190}," m.keys {\n",[32,2138,2139,2142,2145,2148],{"class":34,"line":266},[32,2140,2141],{"class":182},"        if",[32,2143,2144],{"class":190}," k ",[32,2146,2147],{"class":182},"==",[32,2149,2150],{"class":190}," key {\n",[32,2152,2153,2156,2158,2160,2163,2166,2168,2171,2174],{"class":34,"line":272},[32,2154,2155],{"class":190},"            m.keys ",[32,2157,407],{"class":182},[32,2159,1963],{"class":186},[32,2161,2162],{"class":190},"(m.keys[:i], m.keys[i",[32,2164,2165],{"class":182},"+",[32,2167,381],{"class":227},[32,2169,2170],{"class":190},":]",[32,2172,2173],{"class":182},"...",[32,2175,423],{"class":190},[32,2177,2178],{"class":34,"line":278},[32,2179,2180],{"class":182},"            break\n",[32,2182,2183],{"class":34,"line":284},[32,2184,2185],{"class":190},"        }\n",[32,2187,2188],{"class":34,"line":952},[32,2189,509],{"class":190},[32,2191,2192],{"class":34,"line":986},[32,2193,287],{"class":190},[32,2195,2196],{"class":34,"line":998},[32,2197,176],{"emptyLinePlaceholder":175},[32,2199,2200,2202,2204,2206,2208,2210,2212,2214,2216,2218,2220,2222,2224,2227,2229,2231,2233,2235,2237,2239,2241],{"class":34,"line":1012},[32,2201,183],{"class":182},[32,2203,957],{"class":190},[32,2205,1905],{"class":960},[32,2207,795],{"class":182},[32,2209,1843],{"class":186},[32,2211,212],{"class":190},[32,2213,1203],{"class":186},[32,2215,224],{"class":190},[32,2217,1211],{"class":186},[32,2219,1365],{"class":190},[32,2221,1664],{"class":186},[32,2223,206],{"class":190},[32,2225,2226],{"class":960},"fn",[32,2228,1118],{"class":182},[32,2230,206],{"class":190},[32,2232,1203],{"class":186},[32,2234,224],{"class":190},[32,2236,1211],{"class":186},[32,2238,969],{"class":190},[32,2240,635],{"class":182},[32,2242,983],{"class":190},[32,2244,2245,2247,2250,2252,2254],{"class":34,"line":1028},[32,2246,2125],{"class":182},[32,2248,2249],{"class":190}," _, k ",[32,2251,200],{"class":182},[32,2253,2133],{"class":182},[32,2255,2136],{"class":190},[32,2257,2258,2260,2262,2264],{"class":34,"line":1059},[32,2259,2141],{"class":182},[32,2261,456],{"class":182},[32,2263,2226],{"class":186},[32,2265,2266],{"class":190},"(k, m.data[k]) {\n",[32,2268,2269],{"class":34,"line":1064},[32,2270,2180],{"class":182},[32,2272,2273],{"class":34,"line":1589},[32,2274,2185],{"class":190},[32,2276,2277],{"class":34,"line":1605},[32,2278,509],{"class":190},[32,2280,2281],{"class":34,"line":1626},[32,2282,287],{"class":190},[14,2284,2286],{"id":2285},"key-types-what-can-be-a-map-key","Key Types — What Can Be a Map Key",[19,2288,2289,2490,2494],{"language":21},[23,2290,2292],{"className":25,"code":2291,"language":21,"meta":27,"style":27},"\u002F\u002F Keys must be COMPARABLE (support == and !=):\n\u002F\u002F   ✅ bool, int, float, string, rune, pointer, channel, interface\n\u002F\u002F   ✅ array (if element type is comparable)\n\u002F\u002F   ✅ struct (if all fields are comparable)\n\u002F\u002F   ❌ slice, map, function — NOT comparable (can't be keys)\n\n\u002F\u002F Struct key — compound key (cleaner than nested maps):\ntype Point struct{ X, Y int }\ngrid := map[Point]string{\n    {0, 0}: \"origin\",\n    {1, 2}: \"target\",\n}\n\n\u002F\u002F ❌ Nested map is slower (two hash lookups) and less clear:\n\u002F\u002F grid := map[int]map[int]string{}  \u002F\u002F grid[1][2] — two lookups\n\n\u002F\u002F Array key — fixed-size byte sequence as key:\npaths := map[[32]byte]*Node{}  \u002F\u002F SHA-256 hash → node\n\n\u002F\u002F For a \"string key\" that's a byte slice — convert to string:\n\u002F\u002F m[string(byteSlice)] = value\n\u002F\u002F ⚠️ This allocates (string(bytes) copies). For high-frequency keys,\n\u002F\u002F use a string from the start (avoid the conversion).\n",[29,2293,2294,2299,2304,2309,2314,2319,2323,2328,2344,2365,2386,2403,2407,2411,2416,2424,2428,2433,2466,2470,2475,2480,2485],{"__ignoreMap":27},[32,2295,2296],{"class":34,"line":35},[32,2297,2298],{"class":38},"\u002F\u002F Keys must be COMPARABLE (support == and !=):\n",[32,2300,2301],{"class":34,"line":42},[32,2302,2303],{"class":38},"\u002F\u002F   ✅ bool, int, float, string, rune, pointer, channel, interface\n",[32,2305,2306],{"class":34,"line":48},[32,2307,2308],{"class":38},"\u002F\u002F   ✅ array (if element type is comparable)\n",[32,2310,2311],{"class":34,"line":54},[32,2312,2313],{"class":38},"\u002F\u002F   ✅ struct (if all fields are comparable)\n",[32,2315,2316],{"class":34,"line":60},[32,2317,2318],{"class":38},"\u002F\u002F   ❌ slice, map, function — NOT comparable (can't be keys)\n",[32,2320,2321],{"class":34,"line":66},[32,2322,176],{"emptyLinePlaceholder":175},[32,2324,2325],{"class":34,"line":72},[32,2326,2327],{"class":38},"\u002F\u002F Struct key — compound key (cleaner than nested maps):\n",[32,2329,2330,2332,2335,2337,2340,2342],{"class":34,"line":78},[32,2331,618],{"class":182},[32,2333,2334],{"class":186}," Point",[32,2336,624],{"class":182},[32,2338,2339],{"class":190},"{ X, Y ",[32,2341,221],{"class":182},[32,2343,638],{"class":190},[32,2345,2346,2349,2351,2353,2355,2358,2360,2362],{"class":34,"line":84},[32,2347,2348],{"class":190},"grid ",[32,2350,200],{"class":182},[32,2352,360],{"class":182},[32,2354,212],{"class":190},[32,2356,2357],{"class":186},"Point",[32,2359,218],{"class":190},[32,2361,215],{"class":182},[32,2363,2364],{"class":190},"{\n",[32,2366,2367,2370,2373,2375,2377,2380,2383],{"class":34,"line":90},[32,2368,2369],{"class":190},"    {",[32,2371,2372],{"class":227},"0",[32,2374,224],{"class":190},[32,2376,2372],{"class":227},[32,2378,2379],{"class":190},"}: ",[32,2381,2382],{"class":374},"\"origin\"",[32,2384,2385],{"class":190},",\n",[32,2387,2388,2390,2392,2394,2396,2398,2401],{"class":34,"line":96},[32,2389,2369],{"class":190},[32,2391,381],{"class":227},[32,2393,224],{"class":190},[32,2395,391],{"class":227},[32,2397,2379],{"class":190},[32,2399,2400],{"class":374},"\"target\"",[32,2402,2385],{"class":190},[32,2404,2405],{"class":34,"line":102},[32,2406,287],{"class":190},[32,2408,2409],{"class":34,"line":108},[32,2410,176],{"emptyLinePlaceholder":175},[32,2412,2413],{"class":34,"line":114},[32,2414,2415],{"class":38},"\u002F\u002F ❌ Nested map is slower (two hash lookups) and less clear:\n",[32,2417,2418,2421],{"class":34,"line":120},[32,2419,2420],{"class":38},"\u002F\u002F grid := map[int]map[int]string{}",[32,2422,2423],{"class":38},"  \u002F\u002F grid[1][2] — two lookups\n",[32,2425,2426],{"class":34,"line":125},[32,2427,176],{"emptyLinePlaceholder":175},[32,2429,2430],{"class":34,"line":131},[32,2431,2432],{"class":38},"\u002F\u002F Array key — fixed-size byte sequence as key:\n",[32,2434,2435,2438,2440,2442,2445,2448,2450,2453,2455,2457,2460,2463],{"class":34,"line":137},[32,2436,2437],{"class":190},"paths ",[32,2439,200],{"class":182},[32,2441,360],{"class":182},[32,2443,2444],{"class":190},"[[",[32,2446,2447],{"class":227},"32",[32,2449,218],{"class":190},[32,2451,2452],{"class":182},"byte",[32,2454,218],{"class":190},[32,2456,795],{"class":182},[32,2458,2459],{"class":186},"Node",[32,2461,2462],{"class":190},"{}  ",[32,2464,2465],{"class":38},"\u002F\u002F SHA-256 hash → node\n",[32,2467,2468],{"class":34,"line":143},[32,2469,176],{"emptyLinePlaceholder":175},[32,2471,2472],{"class":34,"line":148},[32,2473,2474],{"class":38},"\u002F\u002F For a \"string key\" that's a byte slice — convert to string:\n",[32,2476,2477],{"class":34,"line":154},[32,2478,2479],{"class":38},"\u002F\u002F m[string(byteSlice)] = value\n",[32,2481,2482],{"class":34,"line":160},[32,2483,2484],{"class":38},"\u002F\u002F ⚠️ This allocates (string(bytes) copies). For high-frequency keys,\n",[32,2486,2487],{"class":34,"line":166},[32,2488,2489],{"class":38},"\u002F\u002F use a string from the start (avoid the conversion).\n",[14,2491,2493],{"id":2492},"iteration-randomized-order-and-safe-deletion","Iteration — Randomized Order and Safe Deletion",[19,2495,2496,2780,2784,2879,2883,3014,3018],{"language":21},[23,2497,2499],{"className":25,"code":2498,"language":21,"meta":27,"style":27},"func iteration() {\n    m := map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4}\n\n    \u002F\u002F Iteration order is RANDOMIZED (intentionally — prevents code\n    \u002F\u002F from depending on order, which would break on different Go versions):\n    for k, v := range m {\n        fmt.Println(k, v)  \u002F\u002F order varies each run\n    }\n\n    \u002F\u002F Ordered iteration — extract and sort keys:\n    keys := make([]string, 0, len(m))\n    for k := range m {\n        keys = append(keys, k)\n    }\n    sort.Strings(keys)\n    for _, k := range keys {\n        fmt.Println(k, m[k])  \u002F\u002F deterministic: a, b, c, d\n    }\n\n    \u002F\u002F Safe deletion during iteration:\n    for k := range m {\n        delete(m, k)  \u002F\u002F ✅ safe — Go explicitly allows this\n    }\n    fmt.Println(len(m))  \u002F\u002F 0\n\n    \u002F\u002F ⚠️ Adding keys during iteration is UNspecified:\n    \u002F\u002F new keys may or may not be iterated — don't rely on this behavior\n}\n",[29,2500,2501,2510,2563,2567,2572,2577,2591,2603,2607,2611,2616,2642,2654,2666,2670,2681,2694,2706,2710,2714,2719,2731,2742,2746,2762,2766,2771,2776],{"__ignoreMap":27},[32,2502,2503,2505,2508],{"class":34,"line":35},[32,2504,183],{"class":182},[32,2506,2507],{"class":186}," iteration",[32,2509,191],{"class":190},[32,2511,2512,2514,2516,2518,2520,2522,2524,2526,2528,2530,2532,2534,2536,2538,2540,2542,2544,2546,2548,2551,2553,2556,2558,2561],{"class":34,"line":42},[32,2513,197],{"class":190},[32,2515,200],{"class":182},[32,2517,360],{"class":182},[32,2519,212],{"class":190},[32,2521,215],{"class":182},[32,2523,218],{"class":190},[32,2525,221],{"class":182},[32,2527,371],{"class":190},[32,2529,375],{"class":374},[32,2531,378],{"class":190},[32,2533,381],{"class":227},[32,2535,224],{"class":190},[32,2537,386],{"class":374},[32,2539,378],{"class":190},[32,2541,391],{"class":227},[32,2543,224],{"class":190},[32,2545,401],{"class":374},[32,2547,378],{"class":190},[32,2549,2550],{"class":227},"3",[32,2552,224],{"class":190},[32,2554,2555],{"class":374},"\"d\"",[32,2557,378],{"class":190},[32,2559,2560],{"class":227},"4",[32,2562,287],{"class":190},[32,2564,2565],{"class":34,"line":48},[32,2566,176],{"emptyLinePlaceholder":175},[32,2568,2569],{"class":34,"line":54},[32,2570,2571],{"class":38},"    \u002F\u002F Iteration order is RANDOMIZED (intentionally — prevents code\n",[32,2573,2574],{"class":34,"line":60},[32,2575,2576],{"class":38},"    \u002F\u002F from depending on order, which would break on different Go versions):\n",[32,2578,2579,2581,2584,2586,2588],{"class":34,"line":66},[32,2580,2125],{"class":182},[32,2582,2583],{"class":190}," k, v ",[32,2585,200],{"class":182},[32,2587,2133],{"class":182},[32,2589,2590],{"class":190}," m {\n",[32,2592,2593,2595,2597,2600],{"class":34,"line":72},[32,2594,469],{"class":190},[32,2596,472],{"class":186},[32,2598,2599],{"class":190},"(k, v)  ",[32,2601,2602],{"class":38},"\u002F\u002F order varies each run\n",[32,2604,2605],{"class":34,"line":78},[32,2606,509],{"class":190},[32,2608,2609],{"class":34,"line":84},[32,2610,176],{"emptyLinePlaceholder":175},[32,2612,2613],{"class":34,"line":90},[32,2614,2615],{"class":38},"    \u002F\u002F Ordered iteration — extract and sort keys:\n",[32,2617,2618,2621,2623,2625,2628,2630,2632,2634,2636,2639],{"class":34,"line":96},[32,2619,2620],{"class":190},"    keys ",[32,2622,200],{"class":182},[32,2624,203],{"class":186},[32,2626,2627],{"class":190},"([]",[32,2629,215],{"class":182},[32,2631,224],{"class":190},[32,2633,2372],{"class":227},[32,2635,224],{"class":190},[32,2637,2638],{"class":186},"len",[32,2640,2641],{"class":190},"(m))\n",[32,2643,2644,2646,2648,2650,2652],{"class":34,"line":102},[32,2645,2125],{"class":182},[32,2647,2144],{"class":190},[32,2649,200],{"class":182},[32,2651,2133],{"class":182},[32,2653,2590],{"class":190},[32,2655,2656,2659,2661,2663],{"class":34,"line":108},[32,2657,2658],{"class":190},"        keys ",[32,2660,407],{"class":182},[32,2662,1963],{"class":186},[32,2664,2665],{"class":190},"(keys, k)\n",[32,2667,2668],{"class":34,"line":114},[32,2669,509],{"class":190},[32,2671,2672,2675,2678],{"class":34,"line":120},[32,2673,2674],{"class":190},"    sort.",[32,2676,2677],{"class":186},"Strings",[32,2679,2680],{"class":190},"(keys)\n",[32,2682,2683,2685,2687,2689,2691],{"class":34,"line":125},[32,2684,2125],{"class":182},[32,2686,2249],{"class":190},[32,2688,200],{"class":182},[32,2690,2133],{"class":182},[32,2692,2693],{"class":190}," keys {\n",[32,2695,2696,2698,2700,2703],{"class":34,"line":131},[32,2697,469],{"class":190},[32,2699,472],{"class":186},[32,2701,2702],{"class":190},"(k, m[k])  ",[32,2704,2705],{"class":38},"\u002F\u002F deterministic: a, b, c, d\n",[32,2707,2708],{"class":34,"line":137},[32,2709,509],{"class":190},[32,2711,2712],{"class":34,"line":143},[32,2713,176],{"emptyLinePlaceholder":175},[32,2715,2716],{"class":34,"line":148},[32,2717,2718],{"class":38},"    \u002F\u002F Safe deletion during iteration:\n",[32,2720,2721,2723,2725,2727,2729],{"class":34,"line":154},[32,2722,2125],{"class":182},[32,2724,2144],{"class":190},[32,2726,200],{"class":182},[32,2728,2133],{"class":182},[32,2730,2590],{"class":190},[32,2732,2733,2736,2739],{"class":34,"line":160},[32,2734,2735],{"class":186},"        delete",[32,2737,2738],{"class":190},"(m, k)  ",[32,2740,2741],{"class":38},"\u002F\u002F ✅ safe — Go explicitly allows this\n",[32,2743,2744],{"class":34,"line":166},[32,2745,509],{"class":190},[32,2747,2748,2750,2752,2754,2756,2759],{"class":34,"line":172},[32,2749,523],{"class":190},[32,2751,472],{"class":186},[32,2753,206],{"class":190},[32,2755,2638],{"class":186},[32,2757,2758],{"class":190},"(m))  ",[32,2760,2761],{"class":38},"\u002F\u002F 0\n",[32,2763,2764],{"class":34,"line":179},[32,2765,176],{"emptyLinePlaceholder":175},[32,2767,2768],{"class":34,"line":194},[32,2769,2770],{"class":38},"    \u002F\u002F ⚠️ Adding keys during iteration is UNspecified:\n",[32,2772,2773],{"class":34,"line":237},[32,2774,2775],{"class":38},"    \u002F\u002F new keys may or may not be iterated — don't rely on this behavior\n",[32,2777,2778],{"class":34,"line":243},[32,2779,287],{"class":190},[14,2781,2783],{"id":2782},"tips-tricks","💡 Tips & Tricks",[2785,2786,2787,2798,2816,2830,2849,2866],"ul",{},[2788,2789,2790,378,2794,2797],"li",{},[2791,2792,2793],"strong",{},"Performance",[29,2795,2796],{},"make(map[K]V, hint)"," pre-allocates buckets when you know the approximate size — avoids the incremental growth\u002Frehashing phase. The hint is not a limit; the map grows as needed.",[2788,2799,2800,2803,2804,2807,2808,2811,2812,2815],{},[2791,2801,2802],{},"Safety",": never use a plain map across goroutines — concurrent writes cause a ",[2791,2805,2806],{},"fatal"," (unrecoverable) error. Use ",[29,2809,2810],{},"sync.RWMutex"," + map for the general case, ",[29,2813,2814],{},"sync.Map"," for write-rarely\u002Fread-many.",[2788,2817,2818,2821,2822,2825,2826,2829],{},[2791,2819,2820],{},"Idiom",": use struct keys for compound keys — ",[29,2823,2824],{},"map[struct{ X, Y int }]Cell"," is cleaner and faster (one hash lookup) than nested maps ",[29,2827,2828],{},"map[int]map[int]Cell"," (two lookups).",[2788,2831,2832,2834,2835,2838,2839,2842,2843,2845,2846,2848],{},[2791,2833,2820],{},": the comma-ok idiom (",[29,2836,2837],{},"v, ok := m[key]",") is essential when the zero value is a valid stored value — ",[29,2840,2841],{},"m[\"missing\"]"," returns ",[29,2844,2372],{},", indistinguishable from a stored ",[29,2847,2372],{},". Always use comma-ok when absence is meaningful.",[2788,2850,2851,2853,2854,2857,2858,2861,2862,2865],{},[2791,2852,2793],{},": store ",[29,2855,2856],{},"*Struct"," in maps when you need to mutate fields — map values aren't addressable, so ",[29,2859,2860],{},"map[int]Struct"," requires copy-out\u002Fmodify\u002Fassign-back for each field update. ",[29,2863,2864],{},"map[int]*Struct"," allows in-place mutation.",[2788,2867,2868,2870,2871,2874,2875,2878],{},[2791,2869,2820],{},": clear a map with ",[29,2872,2873],{},"clear(m)"," (Go 1.21+) — deletes all entries in one call. Faster than re-allocating with ",[29,2876,2877],{},"m = make(map[K]V)",", and keeps the same underlying buckets.",[14,2880,2882],{"id":2881},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2785,2884,2885,2901,2912,2918,2929,2938,2944,2953,2959,2974,2987],{},[2788,2886,2887,378,2890,2893,2894,2897,2898,2900],{},[2791,2888,2889],{},"Writing to nil map panics",[29,2891,2892],{},"var m map[string]int; m[\"a\"] = 1"," → ",[29,2895,2896],{},"panic: assignment to entry in nil map",". Always ",[29,2899,1318],{}," or use a literal.",[2788,2902,2903,378,2906,2893,2909,2911],{},[2791,2904,2905],{},"Reading nil map returns zero value",[29,2907,2908],{},"var m map[string]int; v := m[\"a\"]",[29,2910,2372],{}," (no panic). Can mask uninitialized-map bugs.",[2788,2913,2914,2917],{},[2791,2915,2916],{},"Concurrent map access is fatal",": not a recoverable panic — the program crashes. The runtime detects concurrent writes and aborts immediately.",[2788,2919,2920,378,2923,2926,2927,885],{},[2791,2921,2922],{},"Map values are not addressable",[29,2924,2925],{},"&m[\"a\"]"," is illegal (entries can move during rehashing). Copy out, modify, assign back — or store ",[29,2928,2856],{},[2788,2930,2931,2937],{},[2791,2932,2933,2936],{},[29,2934,2935],{},"m[key].field = value"," is a compile error",": can't take the address of a map value. Use the copy-out pattern or store pointers.",[2788,2939,2940,2943],{},[2791,2941,2942],{},"Map iteration order is randomized",": never depend on iteration order — it changes between runs. Sort keys for stable output.",[2788,2945,2946,378,2949,2952],{},[2791,2947,2948],{},"Deleting during iteration is safe",[29,2950,2951],{},"for k := range m { delete(m, k) }"," is explicitly allowed. Adding keys during iteration is unspecified.",[2788,2954,2955,2958],{},[2791,2956,2957],{},"Slices, maps, functions can't be keys",": they're not comparable. Use a string or struct representation as the key.",[2788,2960,2961,2966,2967,2969,2970,2973],{},[2791,2962,2963,2965],{},[29,2964,2873],{}," (Go 1.21+)",": deletes all entries but keeps the map allocated (buckets retained). ",[29,2968,2877],{}," creates a new map (old GC'd). ",[29,2971,2972],{},"clear"," is faster if you'll reuse the map.",[2788,2975,2976,2982,2983,2986],{},[2791,2977,2978,2981],{},[29,2979,2980],{},"make(map, hint)"," hint is not exact",": the actual bucket count is the next power of 2 ≥ hint. ",[29,2984,2985],{},"make(map[K]V, 100)"," → 128 buckets.",[2788,2988,2989,378,2992,2995,2996,2999,3000,3003,3004,3007,3008,3010,3011,885],{},[2791,2990,2991],{},"Pointer keys compare by address, not value",[29,2993,2994],{},"map[*int]string"," — two ",[29,2997,2998],{},"&x"," and ",[29,3001,3002],{},"&y"," where ",[29,3005,3006],{},"x == y"," are different keys (different addresses). Use ",[29,3009,221],{}," as the key, not ",[29,3012,3013],{},"*int",[14,3015,3017],{"id":3016},"quick-quiz","🧠 Quick Quiz",[19,3019,3020,3141],{"language":21},[23,3021,3023],{"className":25,"code":3022,"language":21,"meta":27,"style":27},"m := map[string]*int{}\nx := 1\ny := 1\nm[\"a\"] = &x\nm[\"b\"] = &y\nfmt.Println(*m[\"a\"] == *m[\"b\"])\nfmt.Println(m[\"a\"] == m[\"b\"])\n",[29,3024,3025,3043,3053,3062,3078,3093,3121],{"__ignoreMap":27},[32,3026,3027,3029,3031,3033,3035,3037,3039,3041],{"class":34,"line":35},[32,3028,1905],{"class":190},[32,3030,200],{"class":182},[32,3032,360],{"class":182},[32,3034,212],{"class":190},[32,3036,215],{"class":182},[32,3038,218],{"class":190},[32,3040,3013],{"class":182},[32,3042,1110],{"class":190},[32,3044,3045,3048,3050],{"class":34,"line":42},[32,3046,3047],{"class":190},"x ",[32,3049,200],{"class":182},[32,3051,3052],{"class":227}," 1\n",[32,3054,3055,3058,3060],{"class":34,"line":48},[32,3056,3057],{"class":190},"y ",[32,3059,200],{"class":182},[32,3061,3052],{"class":227},[32,3063,3064,3067,3069,3071,3073,3075],{"class":34,"line":54},[32,3065,3066],{"class":190},"m[",[32,3068,375],{"class":374},[32,3070,404],{"class":190},[32,3072,407],{"class":182},[32,3074,1302],{"class":182},[32,3076,3077],{"class":190},"x\n",[32,3079,3080,3082,3084,3086,3088,3090],{"class":34,"line":60},[32,3081,3066],{"class":190},[32,3083,386],{"class":374},[32,3085,404],{"class":190},[32,3087,407],{"class":182},[32,3089,1302],{"class":182},[32,3091,3092],{"class":190},"y\n",[32,3094,3095,3098,3100,3102,3104,3106,3108,3110,3112,3114,3116,3118],{"class":34,"line":66},[32,3096,3097],{"class":190},"fmt.",[32,3099,472],{"class":186},[32,3101,206],{"class":190},[32,3103,795],{"class":182},[32,3105,3066],{"class":190},[32,3107,375],{"class":374},[32,3109,404],{"class":190},[32,3111,2147],{"class":182},[32,3113,1053],{"class":182},[32,3115,3066],{"class":190},[32,3117,386],{"class":374},[32,3119,3120],{"class":190},"])\n",[32,3122,3123,3125,3127,3129,3131,3133,3135,3137,3139],{"class":34,"line":72},[32,3124,3097],{"class":190},[32,3126,472],{"class":186},[32,3128,528],{"class":190},[32,3130,375],{"class":374},[32,3132,404],{"class":190},[32,3134,2147],{"class":182},[32,3136,442],{"class":190},[32,3138,386],{"class":374},[32,3140,3120],{"class":190},[3142,3143,3144],"p",{},"What's printed?",[3146,3147,3148,3152,3160,3185,3201],"details",{},[3149,3150,3151],"summary",{},"Answer",[23,3153,3158],{"className":3154,"code":3156,"language":3157},[3155],"language-text","true\nfalse\n","text",[29,3159,3156],{"__ignoreMap":27},[2785,3161,3162,3171],{},[2788,3163,3164,2893,3167,3170],{},[29,3165,3166],{},"*m[\"a\"] == *m[\"b\"]",[29,3168,3169],{},"true"," — the pointed-to values are both 1.",[2788,3172,3173,2893,3176,3178,3179,3181,3182,3184],{},[29,3174,3175],{},"m[\"a\"] == m[\"b\"]",[29,3177,684],{}," — the pointers are different (",[29,3180,2998],{}," ≠ ",[29,3183,3002],{},", different addresses).",[3142,3186,3187,3188,3190,3191,3194,3195,3197,3198,885],{},"This is the key distinction for pointer-keyed maps: ",[29,3189,2994],{}," uses pointer ",[2791,3192,3193],{},"address"," for equality, not the pointed-to value. Two distinct ",[29,3196,3013],{}," variables pointing to equal values are ",[2791,3199,3200],{},"different keys",[3142,3202,3203,3204,3207,3208,3210],{},"If you want value-based equality, use the value as the key: ",[29,3205,3206],{},"map[int]string"," (not ",[29,3209,2994],{},").",[14,3212,3214],{"id":3213},"whats-next","📚 What's Next",[3142,3216,3217,3218,3223],{},"→ ",[3219,3220,3222],"a",{"href":3221},"\u002Fgo\u002F09-structs","09 — Structs"," — field layout, embedding vs inheritance, struct tags, and the zero-value-is-useful idiom.",[3225,3226,3227],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":27,"searchDepth":42,"depth":42,"links":3229},[3230,3231,3232],{"id":16,"depth":42,"text":17},{"id":290,"depth":42,"text":291},{"id":3213,"depth":42,"text":3214},"Hash map internals, bucket layout, the concurrency fatal error, the non-addressable value trap, ordered maps, and concurrent map patterns.","md",{},"\u002Fgo\u002F08-maps",{"title":5,"description":3233},"go\u002F08-maps","8Q_-yTw42q13wyruhvQHYbFHWkuOzDed3KdFpyakYSs",1789924648406]