[{"data":1,"prerenderedAt":2841},["ShallowReactive",2],{"page-\u002Fgo\u002F10-pointers":3},{"id":4,"title":5,"body":6,"description":2834,"extension":2835,"meta":2836,"navigation":105,"path":2837,"seo":2838,"stem":2839,"__hash__":2840},"content\u002Fgo\u002F10-pointers.md","10 — Pointers",{"type":7,"value":8,"toc":2829},"minimark",[9,13,18,2724,2812,2816,2825],[10,11,5],"h1",{"id":12},"_10-pointers",[14,15,17],"h2",{"id":16},"pointer-basics-and-auto-dereferencing","Pointer Basics and Auto-Dereferencing",[19,20,22,407,411],"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 ┌──────────────────────────────────────────────────────────────────────┐\n\u002F\u002F │ &x    │ address of x (creates a *T)                                 │\n\u002F\u002F │ *p    │ value at p (dereference)                                    │\n\u002F\u002F │ *T    │ pointer-to-T type                                           │\n\u002F\u002F │ nil   │ zero value of any pointer type                              │\n\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n\u002F\u002F\n\u002F\u002F Go pointers are SAFE:\n\u002F\u002F   - No pointer arithmetic (except unsafe.Pointer)\n\u002F\u002F   - No dangling pointers (GC keeps data alive while referenced)\n\u002F\u002F   - The compiler decides stack vs heap (escape analysis)\n\nfunc basics() {\n    x := 5\n    p := &x          \u002F\u002F p is *int, points to x (on the stack)\n    fmt.Println(*p)  \u002F\u002F 5 (dereference)\n    *p = 10          \u002F\u002F modify x through the pointer\n    fmt.Println(x)   \u002F\u002F 10\n\n    var pp *int      \u002F\u002F nil pointer (zero value of *int)\n    \u002F\u002F *pp = 5        \u002F\u002F panic: nil pointer dereference (runtime, not compile)\n    if pp != nil {   \u002F\u002F ✅ always check before dereferencing nullable pointers\n        _ = *pp\n    }\n}\n\n\u002F\u002F Struct auto-dereferencing — no -> operator (unlike C):\ntype User struct{ Name string }\n\nfunc autoDeref() {\n    u := &User{Name: \"Alice\"}  \u002F\u002F *User\n    u.Name = \"Bob\"              \u002F\u002F ✅ auto-dereference: equivalent to (*u).Name\n    fmt.Println(u.Name)         \u002F\u002F Bob\n\n    \u002F\u002F This works for fields AND methods:\n    \u002F\u002F u.Method() == (*u).Method() (if value receiver)\n    \u002F\u002F u.Method() == u.Method()    (if pointer receiver — already a pointer)\n}\n","",[29,30,31,40,46,52,58,64,70,76,82,88,94,100,107,122,135,152,173,191,204,209,224,233,253,267,273,279,284,290,311,316,326,352,366,379,384,390,396,402],"code",{"__ignoreMap":27},[32,33,36],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"sdCPZ","\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n",[32,41,43],{"class":34,"line":42},2,[32,44,45],{"class":38},"\u002F\u002F │ &x    │ address of x (creates a *T)                                 │\n",[32,47,49],{"class":34,"line":48},3,[32,50,51],{"class":38},"\u002F\u002F │ *p    │ value at p (dereference)                                    │\n",[32,53,55],{"class":34,"line":54},4,[32,56,57],{"class":38},"\u002F\u002F │ *T    │ pointer-to-T type                                           │\n",[32,59,61],{"class":34,"line":60},5,[32,62,63],{"class":38},"\u002F\u002F │ nil   │ zero value of any pointer type                              │\n",[32,65,67],{"class":34,"line":66},6,[32,68,69],{"class":38},"\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n",[32,71,73],{"class":34,"line":72},7,[32,74,75],{"class":38},"\u002F\u002F\n",[32,77,79],{"class":34,"line":78},8,[32,80,81],{"class":38},"\u002F\u002F Go pointers are SAFE:\n",[32,83,85],{"class":34,"line":84},9,[32,86,87],{"class":38},"\u002F\u002F   - No pointer arithmetic (except unsafe.Pointer)\n",[32,89,91],{"class":34,"line":90},10,[32,92,93],{"class":38},"\u002F\u002F   - No dangling pointers (GC keeps data alive while referenced)\n",[32,95,97],{"class":34,"line":96},11,[32,98,99],{"class":38},"\u002F\u002F   - The compiler decides stack vs heap (escape analysis)\n",[32,101,103],{"class":34,"line":102},12,[32,104,106],{"emptyLinePlaceholder":105},true,"\n",[32,108,110,114,118],{"class":34,"line":109},13,[32,111,113],{"class":112},"svdQ7","func",[32,115,117],{"class":116},"sIsaT"," basics",[32,119,121],{"class":120},"ssxIu","() {\n",[32,123,125,128,131],{"class":34,"line":124},14,[32,126,127],{"class":120},"    x ",[32,129,130],{"class":112},":=",[32,132,134],{"class":133},"snvgF"," 5\n",[32,136,138,141,143,146,149],{"class":34,"line":137},15,[32,139,140],{"class":120},"    p ",[32,142,130],{"class":112},[32,144,145],{"class":112}," &",[32,147,148],{"class":120},"x          ",[32,150,151],{"class":38},"\u002F\u002F p is *int, points to x (on the stack)\n",[32,153,155,158,161,164,167,170],{"class":34,"line":154},16,[32,156,157],{"class":120},"    fmt.",[32,159,160],{"class":116},"Println",[32,162,163],{"class":120},"(",[32,165,166],{"class":112},"*",[32,168,169],{"class":120},"p)  ",[32,171,172],{"class":38},"\u002F\u002F 5 (dereference)\n",[32,174,176,179,182,185,188],{"class":34,"line":175},17,[32,177,178],{"class":112},"    *",[32,180,181],{"class":120},"p ",[32,183,184],{"class":112},"=",[32,186,187],{"class":133}," 10",[32,189,190],{"class":38},"          \u002F\u002F modify x through the pointer\n",[32,192,194,196,198,201],{"class":34,"line":193},18,[32,195,157],{"class":120},[32,197,160],{"class":116},[32,199,200],{"class":120},"(x)   ",[32,202,203],{"class":38},"\u002F\u002F 10\n",[32,205,207],{"class":34,"line":206},19,[32,208,106],{"emptyLinePlaceholder":105},[32,210,212,215,218,221],{"class":34,"line":211},20,[32,213,214],{"class":112},"    var",[32,216,217],{"class":120}," pp ",[32,219,220],{"class":112},"*int",[32,222,223],{"class":38},"      \u002F\u002F nil pointer (zero value of *int)\n",[32,225,227,230],{"class":34,"line":226},21,[32,228,229],{"class":38},"    \u002F\u002F *pp = 5",[32,231,232],{"class":38},"        \u002F\u002F panic: nil pointer dereference (runtime, not compile)\n",[32,234,236,239,241,244,247,250],{"class":34,"line":235},22,[32,237,238],{"class":112},"    if",[32,240,217],{"class":120},[32,242,243],{"class":112},"!=",[32,245,246],{"class":133}," nil",[32,248,249],{"class":120}," {   ",[32,251,252],{"class":38},"\u002F\u002F ✅ always check before dereferencing nullable pointers\n",[32,254,256,259,261,264],{"class":34,"line":255},23,[32,257,258],{"class":120},"        _ ",[32,260,184],{"class":112},[32,262,263],{"class":112}," *",[32,265,266],{"class":120},"pp\n",[32,268,270],{"class":34,"line":269},24,[32,271,272],{"class":120},"    }\n",[32,274,276],{"class":34,"line":275},25,[32,277,278],{"class":120},"}\n",[32,280,282],{"class":34,"line":281},26,[32,283,106],{"emptyLinePlaceholder":105},[32,285,287],{"class":34,"line":286},27,[32,288,289],{"class":38},"\u002F\u002F Struct auto-dereferencing — no -> operator (unlike C):\n",[32,291,293,296,299,302,305,308],{"class":34,"line":292},28,[32,294,295],{"class":112},"type",[32,297,298],{"class":116}," User",[32,300,301],{"class":112}," struct",[32,303,304],{"class":120},"{ Name ",[32,306,307],{"class":112},"string",[32,309,310],{"class":120}," }\n",[32,312,314],{"class":34,"line":313},29,[32,315,106],{"emptyLinePlaceholder":105},[32,317,319,321,324],{"class":34,"line":318},30,[32,320,113],{"class":112},[32,322,323],{"class":116}," autoDeref",[32,325,121],{"class":120},[32,327,329,332,334,336,339,342,346,349],{"class":34,"line":328},31,[32,330,331],{"class":120},"    u ",[32,333,130],{"class":112},[32,335,145],{"class":112},[32,337,338],{"class":116},"User",[32,340,341],{"class":120},"{Name: ",[32,343,345],{"class":344},"sJ6F3","\"Alice\"",[32,347,348],{"class":120},"}  ",[32,350,351],{"class":38},"\u002F\u002F *User\n",[32,353,355,358,360,363],{"class":34,"line":354},32,[32,356,357],{"class":120},"    u.Name ",[32,359,184],{"class":112},[32,361,362],{"class":344}," \"Bob\"",[32,364,365],{"class":38},"              \u002F\u002F ✅ auto-dereference: equivalent to (*u).Name\n",[32,367,369,371,373,376],{"class":34,"line":368},33,[32,370,157],{"class":120},[32,372,160],{"class":116},[32,374,375],{"class":120},"(u.Name)         ",[32,377,378],{"class":38},"\u002F\u002F Bob\n",[32,380,382],{"class":34,"line":381},34,[32,383,106],{"emptyLinePlaceholder":105},[32,385,387],{"class":34,"line":386},35,[32,388,389],{"class":38},"    \u002F\u002F This works for fields AND methods:\n",[32,391,393],{"class":34,"line":392},36,[32,394,395],{"class":38},"    \u002F\u002F u.Method() == (*u).Method() (if value receiver)\n",[32,397,399],{"class":34,"line":398},37,[32,400,401],{"class":38},"    \u002F\u002F u.Method() == u.Method()    (if pointer receiver — already a pointer)\n",[32,403,405],{"class":34,"line":404},38,[32,406,278],{"class":120},[14,408,410],{"id":409},"escape-analysis-stack-vs-heap","Escape Analysis — Stack vs Heap",[19,412,413,600,605],{"language":21},[23,414,416],{"className":25,"code":415,"language":21,"meta":27,"style":27},"\u002F\u002F The Go compiler performs ESCAPE ANALYSIS to decide stack vs heap:\n\u002F\u002F   - If a variable's address doesn't escape the function → stack (free)\n\u002F\u002F   - If a variable's address escapes (returned, stored in a global,\n\u002F\u002F     passed to a function that stores it) → heap (GC-managed)\n\u002F\u002F\n\u002F\u002F You DON'T control this — the compiler does. But you can see its decisions:\n\n\u002F\u002F Stack-allocated (no escape):\nfunc stackAlloc() int {\n    x := 42      \u002F\u002F stays on the stack — &x doesn't escape\n    return x\n}\n\n\u002F\u002F Heap-allocated (escapes — address returned):\nfunc heapAlloc() *int {\n    x := 42\n    return &x    \u002F\u002F x escapes to the heap (its address leaves the function)\n}\n\n\u002F\u002F The difference matters:\n\u002F\u002F   stack: zero GC pressure, instant allocation\u002Fdeallocation\n\u002F\u002F   heap:  GC tracks it, adds pause pressure, allocation overhead\n\n\u002F\u002F View escape decisions:\n\u002F\u002F   go build -gcflags='-m' .\u002F...\n\u002F\u002F   go build -gcflags='-m -m' .\u002F...  (verbose — explains WHY)\n\u002F\u002F\n\u002F\u002F Output:\n\u002F\u002F   .\u002Fmain.go:5:2: moved to heap: x    (x escaped because &x was returned)\n\u002F\u002F   .\u002Fmain.go:10:2: x does not escape   (x stays on stack)\n",[29,417,418,423,428,433,438,442,447,451,456,472,484,492,496,500,505,518,527,539,543,547,552,557,562,566,571,576,581,585,590,595],{"__ignoreMap":27},[32,419,420],{"class":34,"line":35},[32,421,422],{"class":38},"\u002F\u002F The Go compiler performs ESCAPE ANALYSIS to decide stack vs heap:\n",[32,424,425],{"class":34,"line":42},[32,426,427],{"class":38},"\u002F\u002F   - If a variable's address doesn't escape the function → stack (free)\n",[32,429,430],{"class":34,"line":48},[32,431,432],{"class":38},"\u002F\u002F   - If a variable's address escapes (returned, stored in a global,\n",[32,434,435],{"class":34,"line":54},[32,436,437],{"class":38},"\u002F\u002F     passed to a function that stores it) → heap (GC-managed)\n",[32,439,440],{"class":34,"line":60},[32,441,75],{"class":38},[32,443,444],{"class":34,"line":66},[32,445,446],{"class":38},"\u002F\u002F You DON'T control this — the compiler does. But you can see its decisions:\n",[32,448,449],{"class":34,"line":72},[32,450,106],{"emptyLinePlaceholder":105},[32,452,453],{"class":34,"line":78},[32,454,455],{"class":38},"\u002F\u002F Stack-allocated (no escape):\n",[32,457,458,460,463,466,469],{"class":34,"line":84},[32,459,113],{"class":112},[32,461,462],{"class":116}," stackAlloc",[32,464,465],{"class":120},"() ",[32,467,468],{"class":112},"int",[32,470,471],{"class":120}," {\n",[32,473,474,476,478,481],{"class":34,"line":90},[32,475,127],{"class":120},[32,477,130],{"class":112},[32,479,480],{"class":133}," 42",[32,482,483],{"class":38},"      \u002F\u002F stays on the stack — &x doesn't escape\n",[32,485,486,489],{"class":34,"line":96},[32,487,488],{"class":112},"    return",[32,490,491],{"class":120}," x\n",[32,493,494],{"class":34,"line":102},[32,495,278],{"class":120},[32,497,498],{"class":34,"line":109},[32,499,106],{"emptyLinePlaceholder":105},[32,501,502],{"class":34,"line":124},[32,503,504],{"class":38},"\u002F\u002F Heap-allocated (escapes — address returned):\n",[32,506,507,509,512,514,516],{"class":34,"line":137},[32,508,113],{"class":112},[32,510,511],{"class":116}," heapAlloc",[32,513,465],{"class":120},[32,515,220],{"class":112},[32,517,471],{"class":120},[32,519,520,522,524],{"class":34,"line":154},[32,521,127],{"class":120},[32,523,130],{"class":112},[32,525,526],{"class":133}," 42\n",[32,528,529,531,533,536],{"class":34,"line":175},[32,530,488],{"class":112},[32,532,145],{"class":112},[32,534,535],{"class":120},"x    ",[32,537,538],{"class":38},"\u002F\u002F x escapes to the heap (its address leaves the function)\n",[32,540,541],{"class":34,"line":193},[32,542,278],{"class":120},[32,544,545],{"class":34,"line":206},[32,546,106],{"emptyLinePlaceholder":105},[32,548,549],{"class":34,"line":211},[32,550,551],{"class":38},"\u002F\u002F The difference matters:\n",[32,553,554],{"class":34,"line":226},[32,555,556],{"class":38},"\u002F\u002F   stack: zero GC pressure, instant allocation\u002Fdeallocation\n",[32,558,559],{"class":34,"line":235},[32,560,561],{"class":38},"\u002F\u002F   heap:  GC tracks it, adds pause pressure, allocation overhead\n",[32,563,564],{"class":34,"line":255},[32,565,106],{"emptyLinePlaceholder":105},[32,567,568],{"class":34,"line":269},[32,569,570],{"class":38},"\u002F\u002F View escape decisions:\n",[32,572,573],{"class":34,"line":275},[32,574,575],{"class":38},"\u002F\u002F   go build -gcflags='-m' .\u002F...\n",[32,577,578],{"class":34,"line":281},[32,579,580],{"class":38},"\u002F\u002F   go build -gcflags='-m -m' .\u002F...  (verbose — explains WHY)\n",[32,582,583],{"class":34,"line":286},[32,584,75],{"class":38},[32,586,587],{"class":34,"line":292},[32,588,589],{"class":38},"\u002F\u002F Output:\n",[32,591,592],{"class":34,"line":313},[32,593,594],{"class":38},"\u002F\u002F   .\u002Fmain.go:5:2: moved to heap: x    (x escaped because &x was returned)\n",[32,596,597],{"class":34,"line":318},[32,598,599],{"class":38},"\u002F\u002F   .\u002Fmain.go:10:2: x does not escape   (x stays on stack)\n",[601,602,604],"h3",{"id":603},"escape-analysis-the-interface-escape","Escape analysis — the interface escape",[19,606,607,774,778],{"language":21},[23,608,610],{"className":25,"code":609,"language":21,"meta":27,"style":27},"\u002F\u002F ⚠️ Assigning a value to an interface often causes an escape —\n\u002F\u002F the interface needs to hold a pointer to the value, so the value\n\u002F\u002F moves to the heap.\n\nfunc interfaceEscape() {\n    x := 42\n    var i any = x  \u002F\u002F x escapes to heap — interface stores (type, *x)\n    _ = i\n}\n\u002F\u002F go build -gcflags='-m': \"x escapes to heap\"\n\n\u002F\u002F ✅ Avoid the escape for known types:\nfunc noEscape() {\n    x := 42\n    processInt(x)  \u002F\u002F x stays on stack — no interface, no escape\n}\n\nfunc processInt(n int) { _ = n }\n\n\u002F\u002F This is why `fmt.Println(x)` causes x to escape — fmt.Println takes\n\u002F\u002F ...any, so every argument is boxed into an interface → heap allocation.\n\u002F\u002F In hot paths, avoid fmt; use strconv or direct writes.\n",[29,611,612,617,622,627,631,640,648,667,677,681,686,690,695,704,712,723,727,731,755,759,764,769],{"__ignoreMap":27},[32,613,614],{"class":34,"line":35},[32,615,616],{"class":38},"\u002F\u002F ⚠️ Assigning a value to an interface often causes an escape —\n",[32,618,619],{"class":34,"line":42},[32,620,621],{"class":38},"\u002F\u002F the interface needs to hold a pointer to the value, so the value\n",[32,623,624],{"class":34,"line":48},[32,625,626],{"class":38},"\u002F\u002F moves to the heap.\n",[32,628,629],{"class":34,"line":54},[32,630,106],{"emptyLinePlaceholder":105},[32,632,633,635,638],{"class":34,"line":60},[32,634,113],{"class":112},[32,636,637],{"class":116}," interfaceEscape",[32,639,121],{"class":120},[32,641,642,644,646],{"class":34,"line":66},[32,643,127],{"class":120},[32,645,130],{"class":112},[32,647,526],{"class":133},[32,649,650,652,655,658,661,664],{"class":34,"line":72},[32,651,214],{"class":112},[32,653,654],{"class":120}," i ",[32,656,657],{"class":116},"any",[32,659,660],{"class":112}," =",[32,662,663],{"class":120}," x  ",[32,665,666],{"class":38},"\u002F\u002F x escapes to heap — interface stores (type, *x)\n",[32,668,669,672,674],{"class":34,"line":78},[32,670,671],{"class":120},"    _ ",[32,673,184],{"class":112},[32,675,676],{"class":120}," i\n",[32,678,679],{"class":34,"line":84},[32,680,278],{"class":120},[32,682,683],{"class":34,"line":90},[32,684,685],{"class":38},"\u002F\u002F go build -gcflags='-m': \"x escapes to heap\"\n",[32,687,688],{"class":34,"line":96},[32,689,106],{"emptyLinePlaceholder":105},[32,691,692],{"class":34,"line":102},[32,693,694],{"class":38},"\u002F\u002F ✅ Avoid the escape for known types:\n",[32,696,697,699,702],{"class":34,"line":109},[32,698,113],{"class":112},[32,700,701],{"class":116}," noEscape",[32,703,121],{"class":120},[32,705,706,708,710],{"class":34,"line":124},[32,707,127],{"class":120},[32,709,130],{"class":112},[32,711,526],{"class":133},[32,713,714,717,720],{"class":34,"line":137},[32,715,716],{"class":116},"    processInt",[32,718,719],{"class":120},"(x)  ",[32,721,722],{"class":38},"\u002F\u002F x stays on stack — no interface, no escape\n",[32,724,725],{"class":34,"line":154},[32,726,278],{"class":120},[32,728,729],{"class":34,"line":175},[32,730,106],{"emptyLinePlaceholder":105},[32,732,733,735,738,740,744,747,750,752],{"class":34,"line":193},[32,734,113],{"class":112},[32,736,737],{"class":116}," processInt",[32,739,163],{"class":120},[32,741,743],{"class":742},"sCrzJ","n",[32,745,746],{"class":112}," int",[32,748,749],{"class":120},") { _ ",[32,751,184],{"class":112},[32,753,754],{"class":120}," n }\n",[32,756,757],{"class":34,"line":206},[32,758,106],{"emptyLinePlaceholder":105},[32,760,761],{"class":34,"line":211},[32,762,763],{"class":38},"\u002F\u002F This is why `fmt.Println(x)` causes x to escape — fmt.Println takes\n",[32,765,766],{"class":34,"line":226},[32,767,768],{"class":38},"\u002F\u002F ...any, so every argument is boxed into an interface → heap allocation.\n",[32,770,771],{"class":34,"line":235},[32,772,773],{"class":38},"\u002F\u002F In hot paths, avoid fmt; use strconv or direct writes.\n",[14,775,777],{"id":776},"when-to-use-pointers-decision-guide","When to Use Pointers — Decision Guide",[19,779,780,1267,1271],{"language":21},[23,781,783],{"className":25,"code":782,"language":21,"meta":27,"style":27},"\u002F\u002F ┌─────────────────────────────────────┬──────────────────────────┐\n\u002F\u002F │ Situation                           │ Use                      │\n\u002F\u002F │ ────────────────────────────────────│ ───────────────────────── │\n\u002F\u002F │ Function modifies caller's data     │ Pointer                  │\n\u002F\u002F │ Large struct (>64 bytes)           │ Pointer (avoid copy)     │\n\u002F\u002F │ Small struct (≤64 bytes, ≤8 words)  │ Value (copy is cheap)    │\n\u002F\u002F │ Need nil as a meaningful value      │ Pointer                  │\n\u002F\u002F │ Method mutates the receiver         │ Pointer receiver         │\n\u002F\u002F │ Storing in an interface             │ Value (or pointer — see │\n\u002F\u002F │                                     │   method set rules)      │\n\u002F\u002F │ Map\u002Fslice\u002Fchan (already reference)  │ Value (pass directly)    │\n\u002F\u002F └─────────────────────────────────────┴──────────────────────────┘\n\n\u002F\u002F ─── Value: small, read-only ───\ntype Point struct{ X, Y float64 }  \u002F\u002F 16 bytes — copy is cheap\n\nfunc distance(p1, p2 Point) float64 {  \u002F\u002F values — no aliasing, no GC\n    dx := p1.X - p2.X\n    dy := p1.Y - p2.Y\n    return math.Sqrt(dx*dx + dy*dy)\n}\n\n\u002F\u002F ─── Pointer: large struct, mutation ───\ntype BigConfig struct {\n    DSN       string\n    Timeouts  map[string]time.Duration\n    Pools     map[string]int\n    Features  []string\n    Middleware []func(http.Handler) http.Handler\n    \u002F\u002F ~200+ bytes — copy is expensive\n}\n\nfunc updateConfig(cfg *BigConfig, key string, val time.Duration) {  \u002F\u002F pointer\n    cfg.Timeouts[key] = val  \u002F\u002F modifies the caller's config\n}\n\n\u002F\u002F ─── Pointer: nil is meaningful ───\ntype OptionalUser struct {\n    User *User  \u002F\u002F nil = no user, non-nil = user present\n}\n\nfunc findUser(id int64) *User {  \u002F\u002F nil = not found\n    if id \u003C= 0 {\n        return nil\n    }\n    return &User{ID: id}\n}\n",[29,784,785,790,795,800,805,810,815,820,825,830,835,840,845,849,854,875,879,910,926,941,970,974,978,983,994,1002,1027,1043,1050,1076,1081,1085,1089,1133,1146,1150,1154,1159,1170,1183,1188,1193,1220,1236,1245,1250,1262],{"__ignoreMap":27},[32,786,787],{"class":34,"line":35},[32,788,789],{"class":38},"\u002F\u002F ┌─────────────────────────────────────┬──────────────────────────┐\n",[32,791,792],{"class":34,"line":42},[32,793,794],{"class":38},"\u002F\u002F │ Situation                           │ Use                      │\n",[32,796,797],{"class":34,"line":48},[32,798,799],{"class":38},"\u002F\u002F │ ────────────────────────────────────│ ───────────────────────── │\n",[32,801,802],{"class":34,"line":54},[32,803,804],{"class":38},"\u002F\u002F │ Function modifies caller's data     │ Pointer                  │\n",[32,806,807],{"class":34,"line":60},[32,808,809],{"class":38},"\u002F\u002F │ Large struct (>64 bytes)           │ Pointer (avoid copy)     │\n",[32,811,812],{"class":34,"line":66},[32,813,814],{"class":38},"\u002F\u002F │ Small struct (≤64 bytes, ≤8 words)  │ Value (copy is cheap)    │\n",[32,816,817],{"class":34,"line":72},[32,818,819],{"class":38},"\u002F\u002F │ Need nil as a meaningful value      │ Pointer                  │\n",[32,821,822],{"class":34,"line":78},[32,823,824],{"class":38},"\u002F\u002F │ Method mutates the receiver         │ Pointer receiver         │\n",[32,826,827],{"class":34,"line":84},[32,828,829],{"class":38},"\u002F\u002F │ Storing in an interface             │ Value (or pointer — see │\n",[32,831,832],{"class":34,"line":90},[32,833,834],{"class":38},"\u002F\u002F │                                     │   method set rules)      │\n",[32,836,837],{"class":34,"line":96},[32,838,839],{"class":38},"\u002F\u002F │ Map\u002Fslice\u002Fchan (already reference)  │ Value (pass directly)    │\n",[32,841,842],{"class":34,"line":102},[32,843,844],{"class":38},"\u002F\u002F └─────────────────────────────────────┴──────────────────────────┘\n",[32,846,847],{"class":34,"line":109},[32,848,106],{"emptyLinePlaceholder":105},[32,850,851],{"class":34,"line":124},[32,852,853],{"class":38},"\u002F\u002F ─── Value: small, read-only ───\n",[32,855,856,858,861,863,866,869,872],{"class":34,"line":137},[32,857,295],{"class":112},[32,859,860],{"class":116}," Point",[32,862,301],{"class":112},[32,864,865],{"class":120},"{ X, Y ",[32,867,868],{"class":112},"float64",[32,870,871],{"class":120}," }  ",[32,873,874],{"class":38},"\u002F\u002F 16 bytes — copy is cheap\n",[32,876,877],{"class":34,"line":154},[32,878,106],{"emptyLinePlaceholder":105},[32,880,881,883,886,888,891,894,897,899,902,904,907],{"class":34,"line":175},[32,882,113],{"class":112},[32,884,885],{"class":116}," distance",[32,887,163],{"class":120},[32,889,890],{"class":742},"p1",[32,892,893],{"class":120},", ",[32,895,896],{"class":742},"p2",[32,898,860],{"class":116},[32,900,901],{"class":120},") ",[32,903,868],{"class":112},[32,905,906],{"class":120}," {  ",[32,908,909],{"class":38},"\u002F\u002F values — no aliasing, no GC\n",[32,911,912,915,917,920,923],{"class":34,"line":193},[32,913,914],{"class":120},"    dx ",[32,916,130],{"class":112},[32,918,919],{"class":120}," p1.X ",[32,921,922],{"class":112},"-",[32,924,925],{"class":120}," p2.X\n",[32,927,928,931,933,936,938],{"class":34,"line":206},[32,929,930],{"class":120},"    dy ",[32,932,130],{"class":112},[32,934,935],{"class":120}," p1.Y ",[32,937,922],{"class":112},[32,939,940],{"class":120}," p2.Y\n",[32,942,943,945,948,951,954,956,959,962,965,967],{"class":34,"line":211},[32,944,488],{"class":112},[32,946,947],{"class":120}," math.",[32,949,950],{"class":116},"Sqrt",[32,952,953],{"class":120},"(dx",[32,955,166],{"class":112},[32,957,958],{"class":120},"dx ",[32,960,961],{"class":112},"+",[32,963,964],{"class":120}," dy",[32,966,166],{"class":112},[32,968,969],{"class":120},"dy)\n",[32,971,972],{"class":34,"line":226},[32,973,278],{"class":120},[32,975,976],{"class":34,"line":235},[32,977,106],{"emptyLinePlaceholder":105},[32,979,980],{"class":34,"line":255},[32,981,982],{"class":38},"\u002F\u002F ─── Pointer: large struct, mutation ───\n",[32,984,985,987,990,992],{"class":34,"line":269},[32,986,295],{"class":112},[32,988,989],{"class":116}," BigConfig",[32,991,301],{"class":112},[32,993,471],{"class":120},[32,995,996,999],{"class":34,"line":275},[32,997,998],{"class":120},"    DSN       ",[32,1000,1001],{"class":112},"string\n",[32,1003,1004,1007,1010,1013,1015,1018,1021,1024],{"class":34,"line":281},[32,1005,1006],{"class":120},"    Timeouts  ",[32,1008,1009],{"class":112},"map",[32,1011,1012],{"class":120},"[",[32,1014,307],{"class":112},[32,1016,1017],{"class":120},"]",[32,1019,1020],{"class":116},"time",[32,1022,1023],{"class":120},".",[32,1025,1026],{"class":116},"Duration\n",[32,1028,1029,1032,1034,1036,1038,1040],{"class":34,"line":286},[32,1030,1031],{"class":120},"    Pools     ",[32,1033,1009],{"class":112},[32,1035,1012],{"class":120},[32,1037,307],{"class":112},[32,1039,1017],{"class":120},[32,1041,1042],{"class":112},"int\n",[32,1044,1045,1048],{"class":34,"line":292},[32,1046,1047],{"class":120},"    Features  []",[32,1049,1001],{"class":112},[32,1051,1052,1055,1057,1059,1062,1064,1067,1069,1071,1073],{"class":34,"line":313},[32,1053,1054],{"class":120},"    Middleware []",[32,1056,113],{"class":112},[32,1058,163],{"class":120},[32,1060,1061],{"class":116},"http",[32,1063,1023],{"class":120},[32,1065,1066],{"class":116},"Handler",[32,1068,901],{"class":120},[32,1070,1061],{"class":116},[32,1072,1023],{"class":120},[32,1074,1075],{"class":116},"Handler\n",[32,1077,1078],{"class":34,"line":318},[32,1079,1080],{"class":38},"    \u002F\u002F ~200+ bytes — copy is expensive\n",[32,1082,1083],{"class":34,"line":328},[32,1084,278],{"class":120},[32,1086,1087],{"class":34,"line":354},[32,1088,106],{"emptyLinePlaceholder":105},[32,1090,1091,1093,1096,1098,1101,1103,1106,1108,1111,1114,1116,1119,1122,1124,1127,1130],{"class":34,"line":368},[32,1092,113],{"class":112},[32,1094,1095],{"class":116}," updateConfig",[32,1097,163],{"class":120},[32,1099,1100],{"class":742},"cfg",[32,1102,263],{"class":112},[32,1104,1105],{"class":116},"BigConfig",[32,1107,893],{"class":120},[32,1109,1110],{"class":742},"key",[32,1112,1113],{"class":112}," string",[32,1115,893],{"class":120},[32,1117,1118],{"class":742},"val",[32,1120,1121],{"class":116}," time",[32,1123,1023],{"class":120},[32,1125,1126],{"class":116},"Duration",[32,1128,1129],{"class":120},") {  ",[32,1131,1132],{"class":38},"\u002F\u002F pointer\n",[32,1134,1135,1138,1140,1143],{"class":34,"line":381},[32,1136,1137],{"class":120},"    cfg.Timeouts[key] ",[32,1139,184],{"class":112},[32,1141,1142],{"class":120}," val  ",[32,1144,1145],{"class":38},"\u002F\u002F modifies the caller's config\n",[32,1147,1148],{"class":34,"line":386},[32,1149,278],{"class":120},[32,1151,1152],{"class":34,"line":392},[32,1153,106],{"emptyLinePlaceholder":105},[32,1155,1156],{"class":34,"line":398},[32,1157,1158],{"class":38},"\u002F\u002F ─── Pointer: nil is meaningful ───\n",[32,1160,1161,1163,1166,1168],{"class":34,"line":404},[32,1162,295],{"class":112},[32,1164,1165],{"class":116}," OptionalUser",[32,1167,301],{"class":112},[32,1169,471],{"class":120},[32,1171,1173,1176,1178,1180],{"class":34,"line":1172},39,[32,1174,1175],{"class":120},"    User ",[32,1177,166],{"class":112},[32,1179,338],{"class":116},[32,1181,1182],{"class":38},"  \u002F\u002F nil = no user, non-nil = user present\n",[32,1184,1186],{"class":34,"line":1185},40,[32,1187,278],{"class":120},[32,1189,1191],{"class":34,"line":1190},41,[32,1192,106],{"emptyLinePlaceholder":105},[32,1194,1196,1198,1201,1203,1206,1209,1211,1213,1215,1217],{"class":34,"line":1195},42,[32,1197,113],{"class":112},[32,1199,1200],{"class":116}," findUser",[32,1202,163],{"class":120},[32,1204,1205],{"class":742},"id",[32,1207,1208],{"class":112}," int64",[32,1210,901],{"class":120},[32,1212,166],{"class":112},[32,1214,338],{"class":116},[32,1216,906],{"class":120},[32,1218,1219],{"class":38},"\u002F\u002F nil = not found\n",[32,1221,1223,1225,1228,1231,1234],{"class":34,"line":1222},43,[32,1224,238],{"class":112},[32,1226,1227],{"class":120}," id ",[32,1229,1230],{"class":112},"\u003C=",[32,1232,1233],{"class":133}," 0",[32,1235,471],{"class":120},[32,1237,1239,1242],{"class":34,"line":1238},44,[32,1240,1241],{"class":112},"        return",[32,1243,1244],{"class":133}," nil\n",[32,1246,1248],{"class":34,"line":1247},45,[32,1249,272],{"class":120},[32,1251,1253,1255,1257,1259],{"class":34,"line":1252},46,[32,1254,488],{"class":112},[32,1256,145],{"class":112},[32,1258,338],{"class":116},[32,1260,1261],{"class":120},"{ID: id}\n",[32,1263,1265],{"class":34,"line":1264},47,[32,1266,278],{"class":120},[14,1268,1270],{"id":1269},"returning-pointers-safe-in-go","Returning Pointers — Safe in Go",[19,1272,1273,1463,1467],{"language":21},[23,1274,1276],{"className":25,"code":1275,"language":21,"meta":27,"style":27},"\u002F\u002F In C, returning &local is a dangling pointer (local is destroyed on return).\n\u002F\u002F In Go, escape analysis moves the local to the heap if its address escapes.\n\u002F\u002F The GC keeps it alive as long as the pointer exists. No dangling pointers.\n\nfunc newUser() *User {\n    u := User{Name: \"Alice\"}  \u002F\u002F local — would be stack in C\n    return &u                  \u002F\u002F u escapes to heap — GC manages its lifetime\n    \u002F\u002F Safe: the compiler sees &u leaves the function, moves u to the heap.\n}\n\n\u002F\u002F This is idiomatic Go — constructors return *T:\nfunc NewServer(addr string) *Server {\n    return &Server{\n        addr:    addr,\n        timeout: 30 * time.Second,\n    }\n}\n\n\u002F\u002F ⚠️ Don't over-optimize by returning values to \"avoid heap allocation\":\nfunc badNewUser() User {  \u002F\u002F returns a value — but if the caller takes &result,\n    return User{Name: \"Alice\"}  \u002F\u002F it escapes anyway. Let the compiler decide.\n}\n",[29,1277,1278,1283,1288,1293,1297,1312,1329,1341,1346,1350,1354,1359,1382,1393,1398,1411,1415,1419,1423,1428,1444,1459],{"__ignoreMap":27},[32,1279,1280],{"class":34,"line":35},[32,1281,1282],{"class":38},"\u002F\u002F In C, returning &local is a dangling pointer (local is destroyed on return).\n",[32,1284,1285],{"class":34,"line":42},[32,1286,1287],{"class":38},"\u002F\u002F In Go, escape analysis moves the local to the heap if its address escapes.\n",[32,1289,1290],{"class":34,"line":48},[32,1291,1292],{"class":38},"\u002F\u002F The GC keeps it alive as long as the pointer exists. No dangling pointers.\n",[32,1294,1295],{"class":34,"line":54},[32,1296,106],{"emptyLinePlaceholder":105},[32,1298,1299,1301,1304,1306,1308,1310],{"class":34,"line":60},[32,1300,113],{"class":112},[32,1302,1303],{"class":116}," newUser",[32,1305,465],{"class":120},[32,1307,166],{"class":112},[32,1309,338],{"class":116},[32,1311,471],{"class":120},[32,1313,1314,1316,1318,1320,1322,1324,1326],{"class":34,"line":66},[32,1315,331],{"class":120},[32,1317,130],{"class":112},[32,1319,298],{"class":116},[32,1321,341],{"class":120},[32,1323,345],{"class":344},[32,1325,348],{"class":120},[32,1327,1328],{"class":38},"\u002F\u002F local — would be stack in C\n",[32,1330,1331,1333,1335,1338],{"class":34,"line":72},[32,1332,488],{"class":112},[32,1334,145],{"class":112},[32,1336,1337],{"class":120},"u                  ",[32,1339,1340],{"class":38},"\u002F\u002F u escapes to heap — GC manages its lifetime\n",[32,1342,1343],{"class":34,"line":78},[32,1344,1345],{"class":38},"    \u002F\u002F Safe: the compiler sees &u leaves the function, moves u to the heap.\n",[32,1347,1348],{"class":34,"line":84},[32,1349,278],{"class":120},[32,1351,1352],{"class":34,"line":90},[32,1353,106],{"emptyLinePlaceholder":105},[32,1355,1356],{"class":34,"line":96},[32,1357,1358],{"class":38},"\u002F\u002F This is idiomatic Go — constructors return *T:\n",[32,1360,1361,1363,1366,1368,1371,1373,1375,1377,1380],{"class":34,"line":102},[32,1362,113],{"class":112},[32,1364,1365],{"class":116}," NewServer",[32,1367,163],{"class":120},[32,1369,1370],{"class":742},"addr",[32,1372,1113],{"class":112},[32,1374,901],{"class":120},[32,1376,166],{"class":112},[32,1378,1379],{"class":116},"Server",[32,1381,471],{"class":120},[32,1383,1384,1386,1388,1390],{"class":34,"line":109},[32,1385,488],{"class":112},[32,1387,145],{"class":112},[32,1389,1379],{"class":116},[32,1391,1392],{"class":120},"{\n",[32,1394,1395],{"class":34,"line":124},[32,1396,1397],{"class":120},"        addr:    addr,\n",[32,1399,1400,1403,1406,1408],{"class":34,"line":137},[32,1401,1402],{"class":120},"        timeout: ",[32,1404,1405],{"class":133},"30",[32,1407,263],{"class":112},[32,1409,1410],{"class":120}," time.Second,\n",[32,1412,1413],{"class":34,"line":154},[32,1414,272],{"class":120},[32,1416,1417],{"class":34,"line":175},[32,1418,278],{"class":120},[32,1420,1421],{"class":34,"line":193},[32,1422,106],{"emptyLinePlaceholder":105},[32,1424,1425],{"class":34,"line":206},[32,1426,1427],{"class":38},"\u002F\u002F ⚠️ Don't over-optimize by returning values to \"avoid heap allocation\":\n",[32,1429,1430,1432,1435,1437,1439,1441],{"class":34,"line":211},[32,1431,113],{"class":112},[32,1433,1434],{"class":116}," badNewUser",[32,1436,465],{"class":120},[32,1438,338],{"class":116},[32,1440,906],{"class":120},[32,1442,1443],{"class":38},"\u002F\u002F returns a value — but if the caller takes &result,\n",[32,1445,1446,1448,1450,1452,1454,1456],{"class":34,"line":226},[32,1447,488],{"class":112},[32,1449,298],{"class":116},[32,1451,341],{"class":120},[32,1453,345],{"class":344},[32,1455,348],{"class":120},[32,1457,1458],{"class":38},"\u002F\u002F it escapes anyway. Let the compiler decide.\n",[32,1460,1461],{"class":34,"line":235},[32,1462,278],{"class":120},[14,1464,1466],{"id":1465},"pointers-and-interface-method-sets","Pointers and Interface Method Sets",[19,1468,1469,1816,1820],{"language":21},[23,1470,1472],{"className":25,"code":1471,"language":21,"meta":27,"style":27},"\u002F\u002F The METHOD SET of a type determines which interfaces it satisfies:\n\u002F\u002F   - Value type T:    methods with VALUE receivers only\n\u002F\u002F   - Pointer type *T: methods with VALUE AND pointer receivers\n\ntype Speaker interface{ Speak() string }\ntype Barker interface{ Bark() string }\n\ntype Dog struct{ Name string }\n\nfunc (d Dog) Speak() string  { return d.Name + \" speaks\" }  \u002F\u002F value receiver\nfunc (d *Dog) Bark() string  { return d.Name + \" barks\" }   \u002F\u002F pointer receiver\n\nfunc methodSetDemo() {\n    var s Speaker\n    s = Dog{Name: \"Rex\"}   \u002F\u002F ✅ Dog has Speak (value receiver)\n    s = &Dog{Name: \"Rex\"}  \u002F\u002F ✅ *Dog has Speak (promoted from value receiver)\n\n    var b Barker\n    \u002F\u002F b = Dog{Name: \"Rex\"}  \u002F\u002F ❌ compile error: Dog's method set lacks Bark (pointer receiver)\n    b = &Dog{Name: \"Rex\"}  \u002F\u002F ✅ *Dog has Bark\n\n    \u002F\u002F RULE: if ANY method has a pointer receiver, you MUST use *T to\n    \u002F\u002F satisfy an interface that includes that method.\n}\n\n\u002F\u002F ─── Consistency rule ───\n\u002F\u002F If any method of a type has a pointer receiver, make ALL methods\n\u002F\u002F pointer receivers. Mixing causes confusion and is flagged by linters.\n\u002F\u002F\n\u002F\u002F ❌ ANTI-PATTERN: mixing receivers\n\u002F\u002F   func (d Dog) Name() string { ... }      \u002F\u002F value receiver\n\u002F\u002F   func (d *Dog) SetName(s string) { ... }  \u002F\u002F pointer receiver\n\u002F\u002F   \u002F\u002F Dog{} satisfies Name but not SetName; &Dog{} satisfies both.\n\u002F\u002F   \u002F\u002F This asymmetry is a common source of interface satisfaction bugs.\n",[29,1473,1474,1479,1484,1489,1493,1515,1535,1539,1554,1558,1598,1635,1639,1648,1658,1678,1697,1701,1711,1719,1739,1743,1748,1753,1757,1761,1766,1771,1776,1780,1785,1793,1801,1809],{"__ignoreMap":27},[32,1475,1476],{"class":34,"line":35},[32,1477,1478],{"class":38},"\u002F\u002F The METHOD SET of a type determines which interfaces it satisfies:\n",[32,1480,1481],{"class":34,"line":42},[32,1482,1483],{"class":38},"\u002F\u002F   - Value type T:    methods with VALUE receivers only\n",[32,1485,1486],{"class":34,"line":48},[32,1487,1488],{"class":38},"\u002F\u002F   - Pointer type *T: methods with VALUE AND pointer receivers\n",[32,1490,1491],{"class":34,"line":54},[32,1492,106],{"emptyLinePlaceholder":105},[32,1494,1495,1497,1500,1503,1506,1509,1511,1513],{"class":34,"line":60},[32,1496,295],{"class":112},[32,1498,1499],{"class":116}," Speaker",[32,1501,1502],{"class":112}," interface",[32,1504,1505],{"class":120},"{ ",[32,1507,1508],{"class":116},"Speak",[32,1510,465],{"class":120},[32,1512,307],{"class":112},[32,1514,310],{"class":120},[32,1516,1517,1519,1522,1524,1526,1529,1531,1533],{"class":34,"line":66},[32,1518,295],{"class":112},[32,1520,1521],{"class":116}," Barker",[32,1523,1502],{"class":112},[32,1525,1505],{"class":120},[32,1527,1528],{"class":116},"Bark",[32,1530,465],{"class":120},[32,1532,307],{"class":112},[32,1534,310],{"class":120},[32,1536,1537],{"class":34,"line":72},[32,1538,106],{"emptyLinePlaceholder":105},[32,1540,1541,1543,1546,1548,1550,1552],{"class":34,"line":78},[32,1542,295],{"class":112},[32,1544,1545],{"class":116}," Dog",[32,1547,301],{"class":112},[32,1549,304],{"class":120},[32,1551,307],{"class":112},[32,1553,310],{"class":120},[32,1555,1556],{"class":34,"line":84},[32,1557,106],{"emptyLinePlaceholder":105},[32,1559,1560,1562,1565,1568,1571,1573,1575,1577,1579,1582,1585,1588,1590,1593,1595],{"class":34,"line":90},[32,1561,113],{"class":112},[32,1563,1564],{"class":120}," (",[32,1566,1567],{"class":742},"d ",[32,1569,1570],{"class":116},"Dog",[32,1572,901],{"class":120},[32,1574,1508],{"class":116},[32,1576,465],{"class":120},[32,1578,307],{"class":112},[32,1580,1581],{"class":120},"  { ",[32,1583,1584],{"class":112},"return",[32,1586,1587],{"class":120}," d.Name ",[32,1589,961],{"class":112},[32,1591,1592],{"class":344}," \" speaks\"",[32,1594,871],{"class":120},[32,1596,1597],{"class":38},"\u002F\u002F value receiver\n",[32,1599,1600,1602,1604,1606,1608,1610,1612,1614,1616,1618,1620,1622,1624,1626,1629,1632],{"class":34,"line":96},[32,1601,113],{"class":112},[32,1603,1564],{"class":120},[32,1605,1567],{"class":742},[32,1607,166],{"class":112},[32,1609,1570],{"class":116},[32,1611,901],{"class":120},[32,1613,1528],{"class":116},[32,1615,465],{"class":120},[32,1617,307],{"class":112},[32,1619,1581],{"class":120},[32,1621,1584],{"class":112},[32,1623,1587],{"class":120},[32,1625,961],{"class":112},[32,1627,1628],{"class":344}," \" barks\"",[32,1630,1631],{"class":120}," }   ",[32,1633,1634],{"class":38},"\u002F\u002F pointer receiver\n",[32,1636,1637],{"class":34,"line":102},[32,1638,106],{"emptyLinePlaceholder":105},[32,1640,1641,1643,1646],{"class":34,"line":109},[32,1642,113],{"class":112},[32,1644,1645],{"class":116}," methodSetDemo",[32,1647,121],{"class":120},[32,1649,1650,1652,1655],{"class":34,"line":124},[32,1651,214],{"class":112},[32,1653,1654],{"class":120}," s ",[32,1656,1657],{"class":116},"Speaker\n",[32,1659,1660,1663,1665,1667,1669,1672,1675],{"class":34,"line":137},[32,1661,1662],{"class":120},"    s ",[32,1664,184],{"class":112},[32,1666,1545],{"class":116},[32,1668,341],{"class":120},[32,1670,1671],{"class":344},"\"Rex\"",[32,1673,1674],{"class":120},"}   ",[32,1676,1677],{"class":38},"\u002F\u002F ✅ Dog has Speak (value receiver)\n",[32,1679,1680,1682,1684,1686,1688,1690,1692,1694],{"class":34,"line":154},[32,1681,1662],{"class":120},[32,1683,184],{"class":112},[32,1685,145],{"class":112},[32,1687,1570],{"class":116},[32,1689,341],{"class":120},[32,1691,1671],{"class":344},[32,1693,348],{"class":120},[32,1695,1696],{"class":38},"\u002F\u002F ✅ *Dog has Speak (promoted from value receiver)\n",[32,1698,1699],{"class":34,"line":175},[32,1700,106],{"emptyLinePlaceholder":105},[32,1702,1703,1705,1708],{"class":34,"line":193},[32,1704,214],{"class":112},[32,1706,1707],{"class":120}," b ",[32,1709,1710],{"class":116},"Barker\n",[32,1712,1713,1716],{"class":34,"line":206},[32,1714,1715],{"class":38},"    \u002F\u002F b = Dog{Name: \"Rex\"}",[32,1717,1718],{"class":38},"  \u002F\u002F ❌ compile error: Dog's method set lacks Bark (pointer receiver)\n",[32,1720,1721,1724,1726,1728,1730,1732,1734,1736],{"class":34,"line":211},[32,1722,1723],{"class":120},"    b ",[32,1725,184],{"class":112},[32,1727,145],{"class":112},[32,1729,1570],{"class":116},[32,1731,341],{"class":120},[32,1733,1671],{"class":344},[32,1735,348],{"class":120},[32,1737,1738],{"class":38},"\u002F\u002F ✅ *Dog has Bark\n",[32,1740,1741],{"class":34,"line":226},[32,1742,106],{"emptyLinePlaceholder":105},[32,1744,1745],{"class":34,"line":235},[32,1746,1747],{"class":38},"    \u002F\u002F RULE: if ANY method has a pointer receiver, you MUST use *T to\n",[32,1749,1750],{"class":34,"line":255},[32,1751,1752],{"class":38},"    \u002F\u002F satisfy an interface that includes that method.\n",[32,1754,1755],{"class":34,"line":269},[32,1756,278],{"class":120},[32,1758,1759],{"class":34,"line":275},[32,1760,106],{"emptyLinePlaceholder":105},[32,1762,1763],{"class":34,"line":281},[32,1764,1765],{"class":38},"\u002F\u002F ─── Consistency rule ───\n",[32,1767,1768],{"class":34,"line":286},[32,1769,1770],{"class":38},"\u002F\u002F If any method of a type has a pointer receiver, make ALL methods\n",[32,1772,1773],{"class":34,"line":292},[32,1774,1775],{"class":38},"\u002F\u002F pointer receivers. Mixing causes confusion and is flagged by linters.\n",[32,1777,1778],{"class":34,"line":313},[32,1779,75],{"class":38},[32,1781,1782],{"class":34,"line":318},[32,1783,1784],{"class":38},"\u002F\u002F ❌ ANTI-PATTERN: mixing receivers\n",[32,1786,1787,1790],{"class":34,"line":328},[32,1788,1789],{"class":38},"\u002F\u002F   func (d Dog) Name() string { ... }",[32,1791,1792],{"class":38},"      \u002F\u002F value receiver\n",[32,1794,1795,1798],{"class":34,"line":354},[32,1796,1797],{"class":38},"\u002F\u002F   func (d *Dog) SetName(s string) { ... }",[32,1799,1800],{"class":38},"  \u002F\u002F pointer receiver\n",[32,1802,1803,1806],{"class":34,"line":368},[32,1804,1805],{"class":38},"\u002F\u002F",[32,1807,1808],{"class":38},"   \u002F\u002F Dog{} satisfies Name but not SetName; &Dog{} satisfies both.\n",[32,1810,1811,1813],{"class":34,"line":381},[32,1812,1805],{"class":38},[32,1814,1815],{"class":38},"   \u002F\u002F This asymmetry is a common source of interface satisfaction bugs.\n",[14,1817,1819],{"id":1818},"nil-pointer-safety-patterns","Nil Pointer Safety Patterns",[19,1821,1822,2278,2288],{"language":21},[23,1823,1825],{"className":25,"code":1824,"language":21,"meta":27,"style":27},"\u002F\u002F ─── Nil-safe methods (pointer receiver can handle nil) ───\ntype Logger struct{ prefix string }\n\nfunc (l *Logger) Log(msg string) {\n    if l == nil {  \u002F\u002F ✅ check for nil receiver — pointer receivers CAN be nil\n        fmt.Println(\"[null-logger]\", msg)\n        return\n    }\n    fmt.Printf(\"[%s] %s\\n\", l.prefix, msg)\n}\n\nfunc nilSafeDemo() {\n    var l *Logger  \u002F\u002F nil\n    l.Log(\"hello\")  \u002F\u002F ✅ prints \"[null-logger] hello\" — no panic\n    \u002F\u002F This works because the method checks for nil receiver.\n}\n\n\u002F\u002F ─── The nil receiver trap (value receiver) ───\ntype BadLogger struct{ prefix string }\nfunc (b BadLogger) Log(msg string) {  \u002F\u002F VALUE receiver\n    \u002F\u002F b is a copy — if the receiver is nil, Go tries to dereference\n    \u002F\u002F to copy the value → panic\n    fmt.Printf(\"[%s] %s\\n\", b.prefix, msg)\n}\n\nfunc badNilDemo() {\n    var b *BadLogger  \u002F\u002F nil\n    \u002F\u002F b.Log(\"hello\")  \u002F\u002F panic: nil pointer dereference\n    \u002F\u002F Go tries to dereference b (nil) to copy BadLogger → panic.\n    _ = b\n}\n\n\u002F\u002F ─── Production pattern: nil as \"no value\" sentinel ───\ntype Config struct {\n    Timeout *time.Duration  \u002F\u002F nil = no timeout (use default), non-nil = set\n}\n\nfunc (c *Config) GetTimeout() time.Duration {\n    if c.Timeout == nil {\n        return 30 * time.Second  \u002F\u002F default\n    }\n    return *c.Timeout  \u002F\u002F explicit value\n}\n\n\u002F\u002F This pattern (pointer to a value type) lets you distinguish\n\u002F\u002F \"not set\" (nil) from \"set to zero value\" (e.g., *Duration = 0).\n",[29,1826,1827,1832,1848,1852,1881,1898,1913,1918,1922,1949,1953,1957,1966,1979,1997,2002,2006,2010,2015,2030,2057,2062,2067,2088,2092,2096,2105,2117,2125,2130,2139,2143,2147,2152,2163,2179,2183,2187,2216,2229,2244,2248,2260,2264,2268,2273],{"__ignoreMap":27},[32,1828,1829],{"class":34,"line":35},[32,1830,1831],{"class":38},"\u002F\u002F ─── Nil-safe methods (pointer receiver can handle nil) ───\n",[32,1833,1834,1836,1839,1841,1844,1846],{"class":34,"line":42},[32,1835,295],{"class":112},[32,1837,1838],{"class":116}," Logger",[32,1840,301],{"class":112},[32,1842,1843],{"class":120},"{ prefix ",[32,1845,307],{"class":112},[32,1847,310],{"class":120},[32,1849,1850],{"class":34,"line":48},[32,1851,106],{"emptyLinePlaceholder":105},[32,1853,1854,1856,1858,1861,1863,1866,1868,1871,1873,1876,1878],{"class":34,"line":54},[32,1855,113],{"class":112},[32,1857,1564],{"class":120},[32,1859,1860],{"class":742},"l ",[32,1862,166],{"class":112},[32,1864,1865],{"class":116},"Logger",[32,1867,901],{"class":120},[32,1869,1870],{"class":116},"Log",[32,1872,163],{"class":120},[32,1874,1875],{"class":742},"msg",[32,1877,1113],{"class":112},[32,1879,1880],{"class":120},") {\n",[32,1882,1883,1885,1888,1891,1893,1895],{"class":34,"line":60},[32,1884,238],{"class":112},[32,1886,1887],{"class":120}," l ",[32,1889,1890],{"class":112},"==",[32,1892,246],{"class":133},[32,1894,906],{"class":120},[32,1896,1897],{"class":38},"\u002F\u002F ✅ check for nil receiver — pointer receivers CAN be nil\n",[32,1899,1900,1903,1905,1907,1910],{"class":34,"line":66},[32,1901,1902],{"class":120},"        fmt.",[32,1904,160],{"class":116},[32,1906,163],{"class":120},[32,1908,1909],{"class":344},"\"[null-logger]\"",[32,1911,1912],{"class":120},", msg)\n",[32,1914,1915],{"class":34,"line":72},[32,1916,1917],{"class":112},"        return\n",[32,1919,1920],{"class":34,"line":78},[32,1921,272],{"class":120},[32,1923,1924,1926,1929,1931,1934,1937,1940,1943,1946],{"class":34,"line":84},[32,1925,157],{"class":120},[32,1927,1928],{"class":116},"Printf",[32,1930,163],{"class":120},[32,1932,1933],{"class":344},"\"[",[32,1935,1936],{"class":133},"%s",[32,1938,1939],{"class":344},"] ",[32,1941,1942],{"class":133},"%s\\n",[32,1944,1945],{"class":344},"\"",[32,1947,1948],{"class":120},", l.prefix, msg)\n",[32,1950,1951],{"class":34,"line":90},[32,1952,278],{"class":120},[32,1954,1955],{"class":34,"line":96},[32,1956,106],{"emptyLinePlaceholder":105},[32,1958,1959,1961,1964],{"class":34,"line":102},[32,1960,113],{"class":112},[32,1962,1963],{"class":116}," nilSafeDemo",[32,1965,121],{"class":120},[32,1967,1968,1970,1972,1974,1976],{"class":34,"line":109},[32,1969,214],{"class":112},[32,1971,1887],{"class":120},[32,1973,166],{"class":112},[32,1975,1865],{"class":116},[32,1977,1978],{"class":38},"  \u002F\u002F nil\n",[32,1980,1981,1984,1986,1988,1991,1994],{"class":34,"line":124},[32,1982,1983],{"class":120},"    l.",[32,1985,1870],{"class":116},[32,1987,163],{"class":120},[32,1989,1990],{"class":344},"\"hello\"",[32,1992,1993],{"class":120},")  ",[32,1995,1996],{"class":38},"\u002F\u002F ✅ prints \"[null-logger] hello\" — no panic\n",[32,1998,1999],{"class":34,"line":137},[32,2000,2001],{"class":38},"    \u002F\u002F This works because the method checks for nil receiver.\n",[32,2003,2004],{"class":34,"line":154},[32,2005,278],{"class":120},[32,2007,2008],{"class":34,"line":175},[32,2009,106],{"emptyLinePlaceholder":105},[32,2011,2012],{"class":34,"line":193},[32,2013,2014],{"class":38},"\u002F\u002F ─── The nil receiver trap (value receiver) ───\n",[32,2016,2017,2019,2022,2024,2026,2028],{"class":34,"line":206},[32,2018,295],{"class":112},[32,2020,2021],{"class":116}," BadLogger",[32,2023,301],{"class":112},[32,2025,1843],{"class":120},[32,2027,307],{"class":112},[32,2029,310],{"class":120},[32,2031,2032,2034,2036,2039,2042,2044,2046,2048,2050,2052,2054],{"class":34,"line":211},[32,2033,113],{"class":112},[32,2035,1564],{"class":120},[32,2037,2038],{"class":742},"b ",[32,2040,2041],{"class":116},"BadLogger",[32,2043,901],{"class":120},[32,2045,1870],{"class":116},[32,2047,163],{"class":120},[32,2049,1875],{"class":742},[32,2051,1113],{"class":112},[32,2053,1129],{"class":120},[32,2055,2056],{"class":38},"\u002F\u002F VALUE receiver\n",[32,2058,2059],{"class":34,"line":226},[32,2060,2061],{"class":38},"    \u002F\u002F b is a copy — if the receiver is nil, Go tries to dereference\n",[32,2063,2064],{"class":34,"line":235},[32,2065,2066],{"class":38},"    \u002F\u002F to copy the value → panic\n",[32,2068,2069,2071,2073,2075,2077,2079,2081,2083,2085],{"class":34,"line":255},[32,2070,157],{"class":120},[32,2072,1928],{"class":116},[32,2074,163],{"class":120},[32,2076,1933],{"class":344},[32,2078,1936],{"class":133},[32,2080,1939],{"class":344},[32,2082,1942],{"class":133},[32,2084,1945],{"class":344},[32,2086,2087],{"class":120},", b.prefix, msg)\n",[32,2089,2090],{"class":34,"line":269},[32,2091,278],{"class":120},[32,2093,2094],{"class":34,"line":275},[32,2095,106],{"emptyLinePlaceholder":105},[32,2097,2098,2100,2103],{"class":34,"line":281},[32,2099,113],{"class":112},[32,2101,2102],{"class":116}," badNilDemo",[32,2104,121],{"class":120},[32,2106,2107,2109,2111,2113,2115],{"class":34,"line":286},[32,2108,214],{"class":112},[32,2110,1707],{"class":120},[32,2112,166],{"class":112},[32,2114,2041],{"class":116},[32,2116,1978],{"class":38},[32,2118,2119,2122],{"class":34,"line":292},[32,2120,2121],{"class":38},"    \u002F\u002F b.Log(\"hello\")",[32,2123,2124],{"class":38},"  \u002F\u002F panic: nil pointer dereference\n",[32,2126,2127],{"class":34,"line":313},[32,2128,2129],{"class":38},"    \u002F\u002F Go tries to dereference b (nil) to copy BadLogger → panic.\n",[32,2131,2132,2134,2136],{"class":34,"line":318},[32,2133,671],{"class":120},[32,2135,184],{"class":112},[32,2137,2138],{"class":120}," b\n",[32,2140,2141],{"class":34,"line":328},[32,2142,278],{"class":120},[32,2144,2145],{"class":34,"line":354},[32,2146,106],{"emptyLinePlaceholder":105},[32,2148,2149],{"class":34,"line":368},[32,2150,2151],{"class":38},"\u002F\u002F ─── Production pattern: nil as \"no value\" sentinel ───\n",[32,2153,2154,2156,2159,2161],{"class":34,"line":381},[32,2155,295],{"class":112},[32,2157,2158],{"class":116}," Config",[32,2160,301],{"class":112},[32,2162,471],{"class":120},[32,2164,2165,2168,2170,2172,2174,2176],{"class":34,"line":386},[32,2166,2167],{"class":120},"    Timeout ",[32,2169,166],{"class":112},[32,2171,1020],{"class":116},[32,2173,1023],{"class":120},[32,2175,1126],{"class":116},[32,2177,2178],{"class":38},"  \u002F\u002F nil = no timeout (use default), non-nil = set\n",[32,2180,2181],{"class":34,"line":392},[32,2182,278],{"class":120},[32,2184,2185],{"class":34,"line":398},[32,2186,106],{"emptyLinePlaceholder":105},[32,2188,2189,2191,2193,2196,2198,2201,2203,2206,2208,2210,2212,2214],{"class":34,"line":404},[32,2190,113],{"class":112},[32,2192,1564],{"class":120},[32,2194,2195],{"class":742},"c ",[32,2197,166],{"class":112},[32,2199,2200],{"class":116},"Config",[32,2202,901],{"class":120},[32,2204,2205],{"class":116},"GetTimeout",[32,2207,465],{"class":120},[32,2209,1020],{"class":116},[32,2211,1023],{"class":120},[32,2213,1126],{"class":116},[32,2215,471],{"class":120},[32,2217,2218,2220,2223,2225,2227],{"class":34,"line":1172},[32,2219,238],{"class":112},[32,2221,2222],{"class":120}," c.Timeout ",[32,2224,1890],{"class":112},[32,2226,246],{"class":133},[32,2228,471],{"class":120},[32,2230,2231,2233,2236,2238,2241],{"class":34,"line":1185},[32,2232,1241],{"class":112},[32,2234,2235],{"class":133}," 30",[32,2237,263],{"class":112},[32,2239,2240],{"class":120}," time.Second  ",[32,2242,2243],{"class":38},"\u002F\u002F default\n",[32,2245,2246],{"class":34,"line":1190},[32,2247,272],{"class":120},[32,2249,2250,2252,2254,2257],{"class":34,"line":1195},[32,2251,488],{"class":112},[32,2253,263],{"class":112},[32,2255,2256],{"class":120},"c.Timeout  ",[32,2258,2259],{"class":38},"\u002F\u002F explicit value\n",[32,2261,2262],{"class":34,"line":1222},[32,2263,278],{"class":120},[32,2265,2266],{"class":34,"line":1238},[32,2267,106],{"emptyLinePlaceholder":105},[32,2269,2270],{"class":34,"line":1247},[32,2271,2272],{"class":38},"\u002F\u002F This pattern (pointer to a value type) lets you distinguish\n",[32,2274,2275],{"class":34,"line":1252},[32,2276,2277],{"class":38},"\u002F\u002F \"not set\" (nil) from \"set to zero value\" (e.g., *Duration = 0).\n",[14,2279,2281,2284,2285],{"id":2280},"new-vs-t",[29,2282,2283],{},"new"," vs ",[29,2286,2287],{},"&T{}",[19,2289,2290,2382,2386,2452,2456,2637,2641],{"language":21},[23,2291,2293],{"className":25,"code":2292,"language":21,"meta":27,"style":27},"\u002F\u002F new(T) — allocates a zero-valued T, returns *T. Rarely used.\np := new(int)   \u002F\u002F *int, *p = 0\n*p = 5\n\n\u002F\u002F &T{} — idiomatic for structs (can initialize fields):\nu := &User{Name: \"Alice\"}  \u002F\u002F *User, fields initialized\n\n\u002F\u002F `&T{}` is almost always clearer than `new(T)` — you can set fields\n\u002F\u002F in the same expression. Use new only when you need a *T for a\n\u002F\u002F non-struct type and don't want a named variable:\n\u002F\u002F   p := new(int)  vs  var x int; p := &x  — new is slightly cleaner here.\n",[29,2294,2295,2300,2319,2329,2333,2338,2358,2362,2367,2372,2377],{"__ignoreMap":27},[32,2296,2297],{"class":34,"line":35},[32,2298,2299],{"class":38},"\u002F\u002F new(T) — allocates a zero-valued T, returns *T. Rarely used.\n",[32,2301,2302,2304,2306,2309,2311,2313,2316],{"class":34,"line":42},[32,2303,181],{"class":120},[32,2305,130],{"class":112},[32,2307,2308],{"class":116}," new",[32,2310,163],{"class":120},[32,2312,468],{"class":112},[32,2314,2315],{"class":120},")   ",[32,2317,2318],{"class":38},"\u002F\u002F *int, *p = 0\n",[32,2320,2321,2323,2325,2327],{"class":34,"line":48},[32,2322,166],{"class":112},[32,2324,181],{"class":120},[32,2326,184],{"class":112},[32,2328,134],{"class":133},[32,2330,2331],{"class":34,"line":54},[32,2332,106],{"emptyLinePlaceholder":105},[32,2334,2335],{"class":34,"line":60},[32,2336,2337],{"class":38},"\u002F\u002F &T{} — idiomatic for structs (can initialize fields):\n",[32,2339,2340,2343,2345,2347,2349,2351,2353,2355],{"class":34,"line":66},[32,2341,2342],{"class":120},"u ",[32,2344,130],{"class":112},[32,2346,145],{"class":112},[32,2348,338],{"class":116},[32,2350,341],{"class":120},[32,2352,345],{"class":344},[32,2354,348],{"class":120},[32,2356,2357],{"class":38},"\u002F\u002F *User, fields initialized\n",[32,2359,2360],{"class":34,"line":72},[32,2361,106],{"emptyLinePlaceholder":105},[32,2363,2364],{"class":34,"line":78},[32,2365,2366],{"class":38},"\u002F\u002F `&T{}` is almost always clearer than `new(T)` — you can set fields\n",[32,2368,2369],{"class":34,"line":84},[32,2370,2371],{"class":38},"\u002F\u002F in the same expression. Use new only when you need a *T for a\n",[32,2373,2374],{"class":34,"line":90},[32,2375,2376],{"class":38},"\u002F\u002F non-struct type and don't want a named variable:\n",[32,2378,2379],{"class":34,"line":96},[32,2380,2381],{"class":38},"\u002F\u002F   p := new(int)  vs  var x int; p := &x  — new is slightly cleaner here.\n",[14,2383,2385],{"id":2384},"tips-tricks","💡 Tips & Tricks",[2387,2388,2389,2401,2407,2416,2432,2442],"ul",{},[2390,2391,2392,2396,2397,2400],"li",{},[2393,2394,2395],"strong",{},"Performance",": run ",[29,2398,2399],{},"go build -gcflags='-m' .\u002F..."," to see escape analysis — it tells you which variables escape to the heap. In hot paths, eliminating escapes (keeping values on the stack) is the #1 allocation-reduction technique.",[2390,2402,2403,2406],{},[2393,2404,2405],{},"Idiom",": use pointer receivers consistently — if ANY method has a pointer receiver, make ALL methods pointer receivers. Mixing value and pointer receivers causes method-set confusion and is flagged by linters.",[2390,2408,2409,2411,2412,2415],{},[2393,2410,2395],{},": don't return ",[29,2413,2414],{},"*T"," to \"avoid a copy\" for small structs — escape analysis may heap-allocate the pointer, adding GC pressure worse than a value copy. For structs ≤ 64 bytes, value returns are often faster (no allocation, no GC).",[2390,2417,2418,2420,2421,2423,2424,2427,2428,2431],{},[2393,2419,2405],{},": use ",[29,2422,2414],{}," (pointer to a value type) for optional fields where \"not set\" (nil) differs from \"set to zero\" — ",[29,2425,2426],{},"*time.Duration"," where nil = default, ",[29,2429,2430],{},"0"," = no timeout. This is the \"nullability\" pattern for value types.",[2390,2433,2434,2437,2438,2441],{},[2393,2435,2436],{},"Safety",": nil pointer dereference is a runtime panic, not a compile error. Always check ",[29,2439,2440],{},"if p != nil"," before dereferencing nullable pointers. For exported APIs, document nil behavior (\"returns nil if not found\").",[2390,2443,2444,2447,2448,2451],{},[2393,2445,2446],{},"Debug",": ",[29,2449,2450],{},"go build -gcflags='-m -m'"," shows WHY a variable escapes — \"p does not escape because ...\" or \"leaking param: p\". This helps understand which code patterns cause heap allocations.",[14,2453,2455],{"id":2454},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2387,2457,2458,2471,2487,2497,2520,2530,2559,2574,2587,2607,2623],{},[2390,2459,2460,2447,2463,2466,2467,2470],{},[2393,2461,2462],{},"No pointer arithmetic",[29,2464,2465],{},"p++"," (to move to the next element) is illegal (except ",[29,2468,2469],{},"unsafe.Pointer","). Go pointers are references, not computable addresses.",[2390,2472,2473,2447,2479,2482,2483,2486],{},[2393,2474,2475,2478],{},[29,2476,2477],{},"nil"," pointer dereference panics at runtime",[29,2480,2481],{},"*p"," where ",[29,2484,2485],{},"p == nil"," is a runtime panic (not a compile error). Check before dereferencing.",[2390,2488,2489,2496],{},[2393,2490,2491,2492,2495],{},"Returning ",[29,2493,2494],{},"&local"," is safe",": escape analysis moves the local to the heap if its address escapes. The GC manages its lifetime. No dangling pointers in Go.",[2390,2498,2499,2447,2506,2509,2510,2513,2514,2517,2518,1023],{},[2393,2500,2501,2284,2503],{},[29,2502,2287],{},[29,2504,2505],{},"new(T)",[29,2507,2508],{},"&User{Name: \"Alice\"}"," is idiomatic (initializes fields); ",[29,2511,2512],{},"new(User)"," returns a zero-value ",[29,2515,2516],{},"*User"," (no initialization). Prefer ",[29,2519,2287],{},[2390,2521,2522,2525,2526,2529],{},[2393,2523,2524],{},"Pointer to map\u002Fslice\u002Fchan is usually wrong",": these are already reference types (internally pointers). ",[29,2527,2528],{},"*map[K]V"," is a pointer to a map pointer — double indirection. Pass the map directly.",[2390,2531,2532,2447,2535,2538,2539,2542,2543,2546,2547,2550,2551,2554,2555,2558],{},[2393,2533,2534],{},"Copy of a struct with pointer\u002Fslice fields is shallow",[29,2536,2537],{},"a := S{Items: []int{1,2}}; b := a"," — ",[29,2540,2541],{},"b.Items"," shares the same underlying array. ",[29,2544,2545],{},"b.Items[0] = 99"," affects ",[29,2548,2549],{},"a.Items[0]",". Use ",[29,2552,2553],{},"slices.Clone"," or ",[29,2556,2557],{},"copy"," for deep copies.",[2390,2560,2561,2570,2571,2573],{},[2393,2562,2563,2566,2567],{},[29,2564,2565],{},"*p++"," is ",[29,2568,2569],{},"(*p)++",": Go parses ",[29,2572,2565],{}," as dereference-then-increment the value. No C-style ambiguity.",[2390,2575,2576,2447,2579,2582,2583,2586],{},[2393,2577,2578],{},"Passing a large struct by value copies it",[29,2580,2581],{},"func f(u User)"," copies the whole User on every call. For large structs, use ",[29,2584,2585],{},"func f(u *User)",". For small structs (≤ 64 bytes), the value copy is cheaper than the pointer indirection.",[2390,2588,2589,2447,2592,2595,2596,2599,2600,2603,2604,1023],{},[2393,2590,2591],{},"Pointers to loop variables (pre-1.22)",[29,2593,2594],{},"for _, v := range items { save(&v) }"," — pre-1.22, all ",[29,2597,2598],{},"&v"," point to the same ",[29,2601,2602],{},"v"," (final value). 1.22+ fixes this. Portable fix: ",[29,2605,2606],{},"v := v; save(&v)",[2390,2608,2609,2447,2612,2615,2616,2619,2620,2622],{},[2393,2610,2611],{},"Interface boxing causes escape",[29,2613,2614],{},"var i any = x"," moves ",[29,2617,2618],{},"x"," to the heap (the interface needs a pointer to the value). In hot paths, avoid passing values through ",[29,2621,657],{}," — use concrete types.",[2390,2624,2625,2447,2630,2632,2633,2636],{},[2393,2626,2627,2629],{},[29,2628,2469],{}," bypasses all safety",[29,2631,2469],{}," can convert between pointer types, do arithmetic, and read\u002Fwrite arbitrary memory. Only for CGO, low-level optimization, or ",[29,2634,2635],{},"reflect",". Misuse causes crashes, data corruption, and security holes.",[14,2638,2640],{"id":2639},"quick-quiz","🧠 Quick Quiz",[19,2642,2643,2717],{"language":21},[23,2644,2646],{"className":25,"code":2645,"language":21,"meta":27,"style":27},"func f() *int {\n    x := 42\n    return &x\n}\n\nfunc g() int {\n    x := 42\n    return x\n}\n",[29,2647,2648,2661,2669,2678,2682,2686,2699,2707,2713],{"__ignoreMap":27},[32,2649,2650,2652,2655,2657,2659],{"class":34,"line":35},[32,2651,113],{"class":112},[32,2653,2654],{"class":116}," f",[32,2656,465],{"class":120},[32,2658,220],{"class":112},[32,2660,471],{"class":120},[32,2662,2663,2665,2667],{"class":34,"line":42},[32,2664,127],{"class":120},[32,2666,130],{"class":112},[32,2668,526],{"class":133},[32,2670,2671,2673,2675],{"class":34,"line":48},[32,2672,488],{"class":112},[32,2674,145],{"class":112},[32,2676,2677],{"class":120},"x\n",[32,2679,2680],{"class":34,"line":54},[32,2681,278],{"class":120},[32,2683,2684],{"class":34,"line":60},[32,2685,106],{"emptyLinePlaceholder":105},[32,2687,2688,2690,2693,2695,2697],{"class":34,"line":66},[32,2689,113],{"class":112},[32,2691,2692],{"class":116}," g",[32,2694,465],{"class":120},[32,2696,468],{"class":112},[32,2698,471],{"class":120},[32,2700,2701,2703,2705],{"class":34,"line":72},[32,2702,127],{"class":120},[32,2704,130],{"class":112},[32,2706,526],{"class":133},[32,2708,2709,2711],{"class":34,"line":78},[32,2710,488],{"class":112},[32,2712,491],{"class":120},[32,2714,2715],{"class":34,"line":84},[32,2716,278],{"class":120},[2718,2719,2720,2721,2723],"p",{},"Which function's ",[29,2722,2618],{}," escapes to the heap, and why?",[2725,2726,2727,2731,2757,2770,2773,2806],"details",{},[2728,2729,2730],"summary",{},"Answer",[2718,2732,2733,2742,2743,2746,2747,2749,2750,2752,2753,2756],{},[2393,2734,2735,2738,2739,2741],{},[29,2736,2737],{},"f()","'s ",[29,2740,2618],{}," escapes to the heap."," ",[29,2744,2745],{},"&x"," is returned, so ",[29,2748,2618],{},"'s address leaves the function. Escape analysis detects this and moves ",[29,2751,2618],{}," to the heap so the GC can manage its lifetime after ",[29,2754,2755],{},"f"," returns.",[2718,2758,2759,2742,2767,2769],{},[2393,2760,2761,2738,2764,2766],{},[29,2762,2763],{},"g()",[29,2765,2618],{}," stays on the stack.",[29,2768,2618],{}," is returned by value (copied to the caller), and its address never escapes. No heap allocation.",[2718,2771,2772],{},"You can verify:",[23,2774,2778],{"className":2775,"code":2776,"language":2777,"meta":27,"style":27},"language-bash shiki shiki-themes github-light github-dark","go build -gcflags='-m' main.go\n# .\u002Fmain.go:2:2: moved to heap: x    ← f's x escapes\n# (g's x doesn't appear — it stays on the stack, no message)\n","bash",[29,2779,2780,2796,2801],{"__ignoreMap":27},[32,2781,2782,2784,2787,2790,2793],{"class":34,"line":35},[32,2783,21],{"class":116},[32,2785,2786],{"class":344}," build",[32,2788,2789],{"class":133}," -gcflags=",[32,2791,2792],{"class":344},"'-m'",[32,2794,2795],{"class":344}," main.go\n",[32,2797,2798],{"class":34,"line":42},[32,2799,2800],{"class":38},"# .\u002Fmain.go:2:2: moved to heap: x    ← f's x escapes\n",[32,2802,2803],{"class":34,"line":48},[32,2804,2805],{"class":38},"# (g's x doesn't appear — it stays on the stack, no message)\n",[2718,2807,2808,2809,2811],{},"The lesson: returning ",[29,2810,2745],{}," forces a heap allocation. For small types, returning the value (not the pointer) keeps it on the stack — zero allocation, zero GC pressure. Only return pointers when you need to (large structs, nil-sentinel, mutation).",[14,2813,2815],{"id":2814},"whats-next","📚 What's Next",[2718,2817,2818,2819,2824],{},"→ ",[2820,2821,2823],"a",{"href":2822},"\u002Fgo\u002F11-methods-and-receivers","11 — Methods & Receivers"," — value vs pointer receivers, method-set rules, nil receiver methods, and embedding promotion.",[2826,2827,2828],"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 pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}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 .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":27,"searchDepth":42,"depth":42,"links":2830},[2831,2832,2833],{"id":16,"depth":42,"text":17},{"id":409,"depth":42,"text":410},{"id":2814,"depth":42,"text":2815},"Escape analysis, stack vs heap allocation, value vs pointer receiver method sets, nil safety patterns, and when pointers help vs hurt performance.","md",{},"\u002Fgo\u002F10-pointers",{"title":5,"description":2834},"go\u002F10-pointers","3zd1Tp0w6t16VUkb0GBgkI8BAVuaWNce-Bwm1sLXWF4",1789924648429]