[{"data":1,"prerenderedAt":2379},["ShallowReactive",2],{"page-\u002Fgo\u002F13-type-assertions-and-switches":3},{"id":4,"title":5,"body":6,"description":2372,"extension":2373,"meta":2374,"navigation":51,"path":2375,"seo":2376,"stem":2377,"__hash__":2378},"content\u002Fgo\u002F13-type-assertions-and-switches.md","13 — Type Assertions & Type Switches",{"type":7,"value":8,"toc":2367},"minimark",[9,13,18,2363],[10,11,5],"h1",{"id":12},"_13-type-assertions-type-switches",[14,15,17],"h2",{"id":16},"type-assertion-panicking-vs-comma-ok","Type Assertion — Panicking vs Comma-Ok",[19,20,22,339,343,2278,2335,2339],"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 Type assertion extracts the concrete type from an interface.\n\u002F\u002F Two forms: panicking (unsafe) and comma-ok (safe).\n\nfunc assertionDemo() {\n    var i any = \"hello\"\n\n    \u002F\u002F ❌ Panicking form — panics if the type doesn't match:\n    s := i.(string)    \u002F\u002F s = \"hello\" — ok\n    \u002F\u002F n := i.(int)     \u002F\u002F PANIC: interface conversion: interface {} is string, not int\n\n    \u002F\u002F ✅ Comma-ok form — never panics, returns (zero, false) on mismatch:\n    s, ok := i.(string)  \u002F\u002F s = \"hello\", ok = true\n    n, ok := i.(int)     \u002F\u002F n = 0, ok = false — no panic\n\n    \u002F\u002F Idiomatic: use comma-ok in an if-init:\n    if s, ok := i.(string); ok {\n        fmt.Println(\"string of length\", len(s))\n    } else {\n        fmt.Println(\"not a string\")\n    }\n}\n\n\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n\u002F\u002F │ When to use the panicking form:                                      │\n\u002F\u002F │   Only when a mismatch indicates a programming error (a violated     │\n\u002F\u002F │   invariant). Example: you KNOW the interface holds a *Config        │\n\u002F\u002F │   because you put it there — `cfg := i.(*Config)` panics if your    │\n\u002F\u002F │   assumption is wrong, which is a bug you want to catch.             │\n\u002F\u002F │                                                                      │\n\u002F\u002F │ When to use comma-ok:                                                │\n\u002F\u002F │   Whenever the type isn't guaranteed — external input, JSON decode, │\n\u002F\u002F │   optional capabilities. This is the default in production code.     │\n\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n","",[29,30,31,40,46,53,68,87,92,98,119,128,133,139,157,176,181,187,205,229,241,256,262,268,273,279,285,291,297,303,309,315,321,327,333],"code",{"__ignoreMap":27},[32,33,36],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"sdCPZ","\u002F\u002F Type assertion extracts the concrete type from an interface.\n",[32,41,43],{"class":34,"line":42},2,[32,44,45],{"class":38},"\u002F\u002F Two forms: panicking (unsafe) and comma-ok (safe).\n",[32,47,49],{"class":34,"line":48},3,[32,50,52],{"emptyLinePlaceholder":51},true,"\n",[32,54,56,60,64],{"class":34,"line":55},4,[32,57,59],{"class":58},"svdQ7","func",[32,61,63],{"class":62},"sIsaT"," assertionDemo",[32,65,67],{"class":66},"ssxIu","() {\n",[32,69,71,74,77,80,83],{"class":34,"line":70},5,[32,72,73],{"class":58},"    var",[32,75,76],{"class":66}," i ",[32,78,79],{"class":62},"any",[32,81,82],{"class":58}," =",[32,84,86],{"class":85},"sJ6F3"," \"hello\"\n",[32,88,90],{"class":34,"line":89},6,[32,91,52],{"emptyLinePlaceholder":51},[32,93,95],{"class":34,"line":94},7,[32,96,97],{"class":38},"    \u002F\u002F ❌ Panicking form — panics if the type doesn't match:\n",[32,99,101,104,107,110,113,116],{"class":34,"line":100},8,[32,102,103],{"class":66},"    s ",[32,105,106],{"class":58},":=",[32,108,109],{"class":66}," i.(",[32,111,112],{"class":58},"string",[32,114,115],{"class":66},")    ",[32,117,118],{"class":38},"\u002F\u002F s = \"hello\" — ok\n",[32,120,122,125],{"class":34,"line":121},9,[32,123,124],{"class":38},"    \u002F\u002F n := i.(int)",[32,126,127],{"class":38},"     \u002F\u002F PANIC: interface conversion: interface {} is string, not int\n",[32,129,131],{"class":34,"line":130},10,[32,132,52],{"emptyLinePlaceholder":51},[32,134,136],{"class":34,"line":135},11,[32,137,138],{"class":38},"    \u002F\u002F ✅ Comma-ok form — never panics, returns (zero, false) on mismatch:\n",[32,140,142,145,147,149,151,154],{"class":34,"line":141},12,[32,143,144],{"class":66},"    s, ok ",[32,146,106],{"class":58},[32,148,109],{"class":66},[32,150,112],{"class":58},[32,152,153],{"class":66},")  ",[32,155,156],{"class":38},"\u002F\u002F s = \"hello\", ok = true\n",[32,158,160,163,165,167,170,173],{"class":34,"line":159},13,[32,161,162],{"class":66},"    n, ok ",[32,164,106],{"class":58},[32,166,109],{"class":66},[32,168,169],{"class":58},"int",[32,171,172],{"class":66},")     ",[32,174,175],{"class":38},"\u002F\u002F n = 0, ok = false — no panic\n",[32,177,179],{"class":34,"line":178},14,[32,180,52],{"emptyLinePlaceholder":51},[32,182,184],{"class":34,"line":183},15,[32,185,186],{"class":38},"    \u002F\u002F Idiomatic: use comma-ok in an if-init:\n",[32,188,190,193,196,198,200,202],{"class":34,"line":189},16,[32,191,192],{"class":58},"    if",[32,194,195],{"class":66}," s, ok ",[32,197,106],{"class":58},[32,199,109],{"class":66},[32,201,112],{"class":58},[32,203,204],{"class":66},"); ok {\n",[32,206,208,211,214,217,220,223,226],{"class":34,"line":207},17,[32,209,210],{"class":66},"        fmt.",[32,212,213],{"class":62},"Println",[32,215,216],{"class":66},"(",[32,218,219],{"class":85},"\"string of length\"",[32,221,222],{"class":66},", ",[32,224,225],{"class":62},"len",[32,227,228],{"class":66},"(s))\n",[32,230,232,235,238],{"class":34,"line":231},18,[32,233,234],{"class":66},"    } ",[32,236,237],{"class":58},"else",[32,239,240],{"class":66}," {\n",[32,242,244,246,248,250,253],{"class":34,"line":243},19,[32,245,210],{"class":66},[32,247,213],{"class":62},[32,249,216],{"class":66},[32,251,252],{"class":85},"\"not a string\"",[32,254,255],{"class":66},")\n",[32,257,259],{"class":34,"line":258},20,[32,260,261],{"class":66},"    }\n",[32,263,265],{"class":34,"line":264},21,[32,266,267],{"class":66},"}\n",[32,269,271],{"class":34,"line":270},22,[32,272,52],{"emptyLinePlaceholder":51},[32,274,276],{"class":34,"line":275},23,[32,277,278],{"class":38},"\u002F\u002F ┌──────────────────────────────────────────────────────────────────────┐\n",[32,280,282],{"class":34,"line":281},24,[32,283,284],{"class":38},"\u002F\u002F │ When to use the panicking form:                                      │\n",[32,286,288],{"class":34,"line":287},25,[32,289,290],{"class":38},"\u002F\u002F │   Only when a mismatch indicates a programming error (a violated     │\n",[32,292,294],{"class":34,"line":293},26,[32,295,296],{"class":38},"\u002F\u002F │   invariant). Example: you KNOW the interface holds a *Config        │\n",[32,298,300],{"class":34,"line":299},27,[32,301,302],{"class":38},"\u002F\u002F │   because you put it there — `cfg := i.(*Config)` panics if your    │\n",[32,304,306],{"class":34,"line":305},28,[32,307,308],{"class":38},"\u002F\u002F │   assumption is wrong, which is a bug you want to catch.             │\n",[32,310,312],{"class":34,"line":311},29,[32,313,314],{"class":38},"\u002F\u002F │                                                                      │\n",[32,316,318],{"class":34,"line":317},30,[32,319,320],{"class":38},"\u002F\u002F │ When to use comma-ok:                                                │\n",[32,322,324],{"class":34,"line":323},31,[32,325,326],{"class":38},"\u002F\u002F │   Whenever the type isn't guaranteed — external input, JSON decode, │\n",[32,328,330],{"class":34,"line":329},32,[32,331,332],{"class":38},"\u002F\u002F │   optional capabilities. This is the default in production code.     │\n",[32,334,336],{"class":34,"line":335},33,[32,337,338],{"class":38},"\u002F\u002F └──────────────────────────────────────────────────────────────────────┘\n",[14,340,342],{"id":341},"type-switch-multi-type-dispatch","Type Switch — Multi-Type Dispatch",[19,344,345,804,808],{"language":21},[23,346,348],{"className":25,"code":347,"language":21,"meta":27,"style":27},"\u002F\u002F The type switch dispatches on the dynamic type of an interface.\n\u002F\u002F Each case binds the variable to the asserted type.\n\nfunc describe(i any) string {\n    switch v := i.(type) {\n    case nil:\n        return \"nil\"\n    case int:\n        return fmt.Sprintf(\"int: %d\", v)        \u002F\u002F v is int\n    case string:\n        return fmt.Sprintf(\"string: %q\", v)    \u002F\u002F v is string\n    case []byte:\n        return fmt.Sprintf(\"bytes: %x\", v)      \u002F\u002F v is []byte\n    case error:\n        return v.Error()                         \u002F\u002F v is error interface\n    default:\n        return fmt.Sprintf(\"unknown %T: %v\", v, v)\n    }\n}\n\n\u002F\u002F ─── Multiple types in one case ───\nfunc numericType(i any) {\n    switch v := i.(type) {\n    case int, int8, int16, int32, int64:\n        \u002F\u002F ⚠️ v is `any` here (not int or int64) — could be any of them\n        \u002F\u002F Must type-assert again to use as a specific type:\n        fmt.Printf(\"integer: %v\\n\", v)\n    case float32, float64:\n        fmt.Printf(\"float: %v\\n\", v)\n    }\n}\n\n\u002F\u002F ─── Type switch with init statement ───\nfunc switchWithInit(i any) {\n    switch v := i.(type); v {\n    case int:\n        _ = v\n    }\n}\n",[29,349,350,355,360,364,387,405,417,425,434,461,470,494,506,530,539,555,562,589,593,597,601,606,621,635,663,668,673,693,707,724,728,732,736,741,757,773,782,794,799],{"__ignoreMap":27},[32,351,352],{"class":34,"line":35},[32,353,354],{"class":38},"\u002F\u002F The type switch dispatches on the dynamic type of an interface.\n",[32,356,357],{"class":34,"line":42},[32,358,359],{"class":38},"\u002F\u002F Each case binds the variable to the asserted type.\n",[32,361,362],{"class":34,"line":48},[32,363,52],{"emptyLinePlaceholder":51},[32,365,366,368,371,373,377,380,383,385],{"class":34,"line":55},[32,367,59],{"class":58},[32,369,370],{"class":62}," describe",[32,372,216],{"class":66},[32,374,376],{"class":375},"sCrzJ","i",[32,378,379],{"class":62}," any",[32,381,382],{"class":66},") ",[32,384,112],{"class":58},[32,386,240],{"class":66},[32,388,389,392,395,397,399,402],{"class":34,"line":70},[32,390,391],{"class":58},"    switch",[32,393,394],{"class":66}," v ",[32,396,106],{"class":58},[32,398,109],{"class":66},[32,400,401],{"class":58},"type",[32,403,404],{"class":66},") {\n",[32,406,407,410,414],{"class":34,"line":89},[32,408,409],{"class":58},"    case",[32,411,413],{"class":412},"snvgF"," nil",[32,415,416],{"class":66},":\n",[32,418,419,422],{"class":34,"line":94},[32,420,421],{"class":58},"        return",[32,423,424],{"class":85}," \"nil\"\n",[32,426,427,429,432],{"class":34,"line":100},[32,428,409],{"class":58},[32,430,431],{"class":58}," int",[32,433,416],{"class":66},[32,435,436,438,441,444,446,449,452,455,458],{"class":34,"line":121},[32,437,421],{"class":58},[32,439,440],{"class":66}," fmt.",[32,442,443],{"class":62},"Sprintf",[32,445,216],{"class":66},[32,447,448],{"class":85},"\"int: ",[32,450,451],{"class":412},"%d",[32,453,454],{"class":85},"\"",[32,456,457],{"class":66},", v)        ",[32,459,460],{"class":38},"\u002F\u002F v is int\n",[32,462,463,465,468],{"class":34,"line":130},[32,464,409],{"class":58},[32,466,467],{"class":58}," string",[32,469,416],{"class":66},[32,471,472,474,476,478,480,483,486,488,491],{"class":34,"line":135},[32,473,421],{"class":58},[32,475,440],{"class":66},[32,477,443],{"class":62},[32,479,216],{"class":66},[32,481,482],{"class":85},"\"string: ",[32,484,485],{"class":412},"%q",[32,487,454],{"class":85},[32,489,490],{"class":66},", v)    ",[32,492,493],{"class":38},"\u002F\u002F v is string\n",[32,495,496,498,501,504],{"class":34,"line":141},[32,497,409],{"class":58},[32,499,500],{"class":66}," []",[32,502,503],{"class":58},"byte",[32,505,416],{"class":66},[32,507,508,510,512,514,516,519,522,524,527],{"class":34,"line":159},[32,509,421],{"class":58},[32,511,440],{"class":66},[32,513,443],{"class":62},[32,515,216],{"class":66},[32,517,518],{"class":85},"\"bytes: ",[32,520,521],{"class":412},"%x",[32,523,454],{"class":85},[32,525,526],{"class":66},", v)      ",[32,528,529],{"class":38},"\u002F\u002F v is []byte\n",[32,531,532,534,537],{"class":34,"line":178},[32,533,409],{"class":58},[32,535,536],{"class":58}," error",[32,538,416],{"class":66},[32,540,541,543,546,549,552],{"class":34,"line":183},[32,542,421],{"class":58},[32,544,545],{"class":66}," v.",[32,547,548],{"class":62},"Error",[32,550,551],{"class":66},"()                         ",[32,553,554],{"class":38},"\u002F\u002F v is error interface\n",[32,556,557,560],{"class":34,"line":189},[32,558,559],{"class":58},"    default",[32,561,416],{"class":66},[32,563,564,566,568,570,572,575,578,581,584,586],{"class":34,"line":207},[32,565,421],{"class":58},[32,567,440],{"class":66},[32,569,443],{"class":62},[32,571,216],{"class":66},[32,573,574],{"class":85},"\"unknown ",[32,576,577],{"class":412},"%T",[32,579,580],{"class":85},": ",[32,582,583],{"class":412},"%v",[32,585,454],{"class":85},[32,587,588],{"class":66},", v, v)\n",[32,590,591],{"class":34,"line":231},[32,592,261],{"class":66},[32,594,595],{"class":34,"line":243},[32,596,267],{"class":66},[32,598,599],{"class":34,"line":258},[32,600,52],{"emptyLinePlaceholder":51},[32,602,603],{"class":34,"line":264},[32,604,605],{"class":38},"\u002F\u002F ─── Multiple types in one case ───\n",[32,607,608,610,613,615,617,619],{"class":34,"line":270},[32,609,59],{"class":58},[32,611,612],{"class":62}," numericType",[32,614,216],{"class":66},[32,616,376],{"class":375},[32,618,379],{"class":62},[32,620,404],{"class":66},[32,622,623,625,627,629,631,633],{"class":34,"line":275},[32,624,391],{"class":58},[32,626,394],{"class":66},[32,628,106],{"class":58},[32,630,109],{"class":66},[32,632,401],{"class":58},[32,634,404],{"class":66},[32,636,637,639,641,643,646,648,651,653,656,658,661],{"class":34,"line":281},[32,638,409],{"class":58},[32,640,431],{"class":58},[32,642,222],{"class":66},[32,644,645],{"class":58},"int8",[32,647,222],{"class":66},[32,649,650],{"class":58},"int16",[32,652,222],{"class":66},[32,654,655],{"class":58},"int32",[32,657,222],{"class":66},[32,659,660],{"class":58},"int64",[32,662,416],{"class":66},[32,664,665],{"class":34,"line":287},[32,666,667],{"class":38},"        \u002F\u002F ⚠️ v is `any` here (not int or int64) — could be any of them\n",[32,669,670],{"class":34,"line":293},[32,671,672],{"class":38},"        \u002F\u002F Must type-assert again to use as a specific type:\n",[32,674,675,677,680,682,685,688,690],{"class":34,"line":299},[32,676,210],{"class":66},[32,678,679],{"class":62},"Printf",[32,681,216],{"class":66},[32,683,684],{"class":85},"\"integer: ",[32,686,687],{"class":412},"%v\\n",[32,689,454],{"class":85},[32,691,692],{"class":66},", v)\n",[32,694,695,697,700,702,705],{"class":34,"line":305},[32,696,409],{"class":58},[32,698,699],{"class":58}," float32",[32,701,222],{"class":66},[32,703,704],{"class":58},"float64",[32,706,416],{"class":66},[32,708,709,711,713,715,718,720,722],{"class":34,"line":311},[32,710,210],{"class":66},[32,712,679],{"class":62},[32,714,216],{"class":66},[32,716,717],{"class":85},"\"float: ",[32,719,687],{"class":412},[32,721,454],{"class":85},[32,723,692],{"class":66},[32,725,726],{"class":34,"line":317},[32,727,261],{"class":66},[32,729,730],{"class":34,"line":323},[32,731,267],{"class":66},[32,733,734],{"class":34,"line":329},[32,735,52],{"emptyLinePlaceholder":51},[32,737,738],{"class":34,"line":335},[32,739,740],{"class":38},"\u002F\u002F ─── Type switch with init statement ───\n",[32,742,744,746,749,751,753,755],{"class":34,"line":743},34,[32,745,59],{"class":58},[32,747,748],{"class":62}," switchWithInit",[32,750,216],{"class":66},[32,752,376],{"class":375},[32,754,379],{"class":62},[32,756,404],{"class":66},[32,758,760,762,764,766,768,770],{"class":34,"line":759},35,[32,761,391],{"class":58},[32,763,394],{"class":66},[32,765,106],{"class":58},[32,767,109],{"class":66},[32,769,401],{"class":58},[32,771,772],{"class":66},"); v {\n",[32,774,776,778,780],{"class":34,"line":775},36,[32,777,409],{"class":58},[32,779,431],{"class":58},[32,781,416],{"class":66},[32,783,785,788,791],{"class":34,"line":784},37,[32,786,787],{"class":66},"        _ ",[32,789,790],{"class":58},"=",[32,792,793],{"class":66}," v\n",[32,795,797],{"class":34,"line":796},38,[32,798,261],{"class":66},[32,800,802],{"class":34,"line":801},39,[32,803,267],{"class":66},[14,805,807],{"id":806},"interface-to-interface-assertion-capability-checks","Interface-to-Interface Assertion — Capability Checks",[19,809,810,1154,1158],{"language":21},[23,811,813],{"className":25,"code":812,"language":21,"meta":27,"style":27},"\u002F\u002F You can assert that an interface value satisfies ANOTHER interface.\n\u002F\u002F This is \"capability checking\" — does this type also implement X?\n\nfunc capabilityCheck() {\n    var r io.Reader = strings.NewReader(\"hello\")\n\n    \u002F\u002F Does r also satisfy io.Writer? (strings.Reader does NOT)\n    if w, ok := r.(io.Writer); ok {\n        w.Write([]byte(\"...\"))  \u002F\u002F never reached\n    }\n\n    \u002F\u002F Does r satisfy io.ReaderAt? (strings.Reader DOES)\n    if ra, ok := r.(io.ReaderAt); ok {\n        buf := make([]byte, 3)\n        ra.ReadAt(buf, 1)  \u002F\u002F reads \"ell\"\n        fmt.Println(string(buf))  \u002F\u002F \"ell\"\n    }\n}\n\n\u002F\u002F ─── Production pattern: optional capabilities ───\nfunc writeAll(w io.Writer, data []byte) error {\n    \u002F\u002F If w supports io.Closer, close it after writing:\n    if c, ok := w.(io.Closer); ok {\n        defer c.Close()\n    }\n    _, err := w.Write(data)\n    return err\n}\n\n\u002F\u002F The stdlib does this: http.Response.Body is an io.ReadCloser, but\n\u002F\u002F some wrappers only implement io.Reader. Code checks for io.Closer\n\u002F\u002F before calling Close to avoid panics.\n",[29,814,815,820,825,829,838,869,873,878,899,923,927,931,936,956,977,996,1012,1016,1020,1024,1029,1064,1069,1090,1104,1108,1123,1131,1135,1139,1144,1149],{"__ignoreMap":27},[32,816,817],{"class":34,"line":35},[32,818,819],{"class":38},"\u002F\u002F You can assert that an interface value satisfies ANOTHER interface.\n",[32,821,822],{"class":34,"line":42},[32,823,824],{"class":38},"\u002F\u002F This is \"capability checking\" — does this type also implement X?\n",[32,826,827],{"class":34,"line":48},[32,828,52],{"emptyLinePlaceholder":51},[32,830,831,833,836],{"class":34,"line":55},[32,832,59],{"class":58},[32,834,835],{"class":62}," capabilityCheck",[32,837,67],{"class":66},[32,839,840,842,845,848,851,854,856,859,862,864,867],{"class":34,"line":70},[32,841,73],{"class":58},[32,843,844],{"class":66}," r ",[32,846,847],{"class":62},"io",[32,849,850],{"class":66},".",[32,852,853],{"class":62},"Reader",[32,855,82],{"class":58},[32,857,858],{"class":66}," strings.",[32,860,861],{"class":62},"NewReader",[32,863,216],{"class":66},[32,865,866],{"class":85},"\"hello\"",[32,868,255],{"class":66},[32,870,871],{"class":34,"line":89},[32,872,52],{"emptyLinePlaceholder":51},[32,874,875],{"class":34,"line":94},[32,876,877],{"class":38},"    \u002F\u002F Does r also satisfy io.Writer? (strings.Reader does NOT)\n",[32,879,880,882,885,887,890,892,894,897],{"class":34,"line":100},[32,881,192],{"class":58},[32,883,884],{"class":66}," w, ok ",[32,886,106],{"class":58},[32,888,889],{"class":66}," r.(",[32,891,847],{"class":62},[32,893,850],{"class":66},[32,895,896],{"class":62},"Writer",[32,898,204],{"class":66},[32,900,901,904,907,910,912,914,917,920],{"class":34,"line":121},[32,902,903],{"class":66},"        w.",[32,905,906],{"class":62},"Write",[32,908,909],{"class":66},"([]",[32,911,503],{"class":58},[32,913,216],{"class":66},[32,915,916],{"class":85},"\"...\"",[32,918,919],{"class":66},"))  ",[32,921,922],{"class":38},"\u002F\u002F never reached\n",[32,924,925],{"class":34,"line":130},[32,926,261],{"class":66},[32,928,929],{"class":34,"line":135},[32,930,52],{"emptyLinePlaceholder":51},[32,932,933],{"class":34,"line":141},[32,934,935],{"class":38},"    \u002F\u002F Does r satisfy io.ReaderAt? (strings.Reader DOES)\n",[32,937,938,940,943,945,947,949,951,954],{"class":34,"line":159},[32,939,192],{"class":58},[32,941,942],{"class":66}," ra, ok ",[32,944,106],{"class":58},[32,946,889],{"class":66},[32,948,847],{"class":62},[32,950,850],{"class":66},[32,952,953],{"class":62},"ReaderAt",[32,955,204],{"class":66},[32,957,958,961,963,966,968,970,972,975],{"class":34,"line":178},[32,959,960],{"class":66},"        buf ",[32,962,106],{"class":58},[32,964,965],{"class":62}," make",[32,967,909],{"class":66},[32,969,503],{"class":58},[32,971,222],{"class":66},[32,973,974],{"class":412},"3",[32,976,255],{"class":66},[32,978,979,982,985,988,991,993],{"class":34,"line":183},[32,980,981],{"class":66},"        ra.",[32,983,984],{"class":62},"ReadAt",[32,986,987],{"class":66},"(buf, ",[32,989,990],{"class":412},"1",[32,992,153],{"class":66},[32,994,995],{"class":38},"\u002F\u002F reads \"ell\"\n",[32,997,998,1000,1002,1004,1006,1009],{"class":34,"line":189},[32,999,210],{"class":66},[32,1001,213],{"class":62},[32,1003,216],{"class":66},[32,1005,112],{"class":58},[32,1007,1008],{"class":66},"(buf))  ",[32,1010,1011],{"class":38},"\u002F\u002F \"ell\"\n",[32,1013,1014],{"class":34,"line":207},[32,1015,261],{"class":66},[32,1017,1018],{"class":34,"line":231},[32,1019,267],{"class":66},[32,1021,1022],{"class":34,"line":243},[32,1023,52],{"emptyLinePlaceholder":51},[32,1025,1026],{"class":34,"line":258},[32,1027,1028],{"class":38},"\u002F\u002F ─── Production pattern: optional capabilities ───\n",[32,1030,1031,1033,1036,1038,1041,1044,1046,1048,1050,1053,1055,1057,1059,1062],{"class":34,"line":264},[32,1032,59],{"class":58},[32,1034,1035],{"class":62}," writeAll",[32,1037,216],{"class":66},[32,1039,1040],{"class":375},"w",[32,1042,1043],{"class":62}," io",[32,1045,850],{"class":66},[32,1047,896],{"class":62},[32,1049,222],{"class":66},[32,1051,1052],{"class":375},"data",[32,1054,500],{"class":66},[32,1056,503],{"class":58},[32,1058,382],{"class":66},[32,1060,1061],{"class":58},"error",[32,1063,240],{"class":66},[32,1065,1066],{"class":34,"line":270},[32,1067,1068],{"class":38},"    \u002F\u002F If w supports io.Closer, close it after writing:\n",[32,1070,1071,1073,1076,1078,1081,1083,1085,1088],{"class":34,"line":275},[32,1072,192],{"class":58},[32,1074,1075],{"class":66}," c, ok ",[32,1077,106],{"class":58},[32,1079,1080],{"class":66}," w.(",[32,1082,847],{"class":62},[32,1084,850],{"class":66},[32,1086,1087],{"class":62},"Closer",[32,1089,204],{"class":66},[32,1091,1092,1095,1098,1101],{"class":34,"line":281},[32,1093,1094],{"class":58},"        defer",[32,1096,1097],{"class":66}," c.",[32,1099,1100],{"class":62},"Close",[32,1102,1103],{"class":66},"()\n",[32,1105,1106],{"class":34,"line":287},[32,1107,261],{"class":66},[32,1109,1110,1113,1115,1118,1120],{"class":34,"line":293},[32,1111,1112],{"class":66},"    _, err ",[32,1114,106],{"class":58},[32,1116,1117],{"class":66}," w.",[32,1119,906],{"class":62},[32,1121,1122],{"class":66},"(data)\n",[32,1124,1125,1128],{"class":34,"line":299},[32,1126,1127],{"class":58},"    return",[32,1129,1130],{"class":66}," err\n",[32,1132,1133],{"class":34,"line":305},[32,1134,267],{"class":66},[32,1136,1137],{"class":34,"line":311},[32,1138,52],{"emptyLinePlaceholder":51},[32,1140,1141],{"class":34,"line":317},[32,1142,1143],{"class":38},"\u002F\u002F The stdlib does this: http.Response.Body is an io.ReadCloser, but\n",[32,1145,1146],{"class":34,"line":323},[32,1147,1148],{"class":38},"\u002F\u002F some wrappers only implement io.Reader. Code checks for io.Closer\n",[32,1150,1151],{"class":34,"line":329},[32,1152,1153],{"class":38},"\u002F\u002F before calling Close to avoid panics.\n",[14,1155,1157],{"id":1156},"the-json-float64-trap","The JSON float64 Trap",[19,1159,1160,1626,1630],{"language":21},[23,1161,1163],{"className":25,"code":1162,"language":21,"meta":27,"style":27},"\u002F\u002F encoding\u002Fjson decodes numbers as float64 by default.\n\u002F\u002F Type-asserting to int panics — the dynamic type is float64.\n\nfunc jsonTrap() {\n    var data any\n    json.Unmarshal([]byte(`{\"count\": 42, \"price\": 9.99}`), &data)\n\n    m := data.(map[string]any)\n    \u002F\u002F count := m[\"count\"].(int)  \u002F\u002F PANIC: interface is float64, not int\n\n    \u002F\u002F ✅ Assert to float64, then convert:\n    count := int(m[\"count\"].(float64))  \u002F\u002F 42\n    price := m[\"price\"].(float64)      \u002F\u002F 9.99\n\n    \u002F\u002F ✅ Or use comma-ok to handle safely:\n    if f, ok := m[\"count\"].(float64); ok {\n        count := int(f)\n        _ = count\n    }\n}\n\n\u002F\u002F ─── Better: use UseNumber for json.Number (string-backed) ───\nfunc jsonUseNumber() {\n    dec := json.NewDecoder(strings.NewReader(`{\"count\": 42}`))\n    dec.UseNumber()  \u002F\u002F numbers become json.Number (a string)\n    var data any\n    dec.Decode(&data)\n    m := data.(map[string]any)\n    n, _ := m[\"count\"].(json.Number).Int64()  \u002F\u002F parse as int64\n    fmt.Println(n)  \u002F\u002F 42\n}\n\n\u002F\u002F ─── Best: unmarshal into a typed struct ───\ntype Product struct {\n    Count int     `json:\"count\"`\n    Price float64 `json:\"price\"`\n}\nfunc jsonStruct() {\n    var p Product\n    json.Unmarshal([]byte(`{\"count\": 42, \"price\": 9.99}`), &p)\n    fmt.Println(p.Count)  \u002F\u002F 42 (int, not float64)\n}\n",[29,1164,1165,1170,1175,1179,1188,1198,1224,1228,1253,1261,1265,1270,1295,1318,1322,1327,1346,1358,1367,1371,1375,1379,1384,1393,1419,1433,1441,1454,1474,1506,1518,1522,1526,1531,1543,1553,1563,1567,1576,1586,1608,1621],{"__ignoreMap":27},[32,1166,1167],{"class":34,"line":35},[32,1168,1169],{"class":38},"\u002F\u002F encoding\u002Fjson decodes numbers as float64 by default.\n",[32,1171,1172],{"class":34,"line":42},[32,1173,1174],{"class":38},"\u002F\u002F Type-asserting to int panics — the dynamic type is float64.\n",[32,1176,1177],{"class":34,"line":48},[32,1178,52],{"emptyLinePlaceholder":51},[32,1180,1181,1183,1186],{"class":34,"line":55},[32,1182,59],{"class":58},[32,1184,1185],{"class":62}," jsonTrap",[32,1187,67],{"class":66},[32,1189,1190,1192,1195],{"class":34,"line":70},[32,1191,73],{"class":58},[32,1193,1194],{"class":66}," data ",[32,1196,1197],{"class":62},"any\n",[32,1199,1200,1203,1206,1208,1210,1212,1215,1218,1221],{"class":34,"line":89},[32,1201,1202],{"class":66},"    json.",[32,1204,1205],{"class":62},"Unmarshal",[32,1207,909],{"class":66},[32,1209,503],{"class":58},[32,1211,216],{"class":66},[32,1213,1214],{"class":85},"`{\"count\": 42, \"price\": 9.99}`",[32,1216,1217],{"class":66},"), ",[32,1219,1220],{"class":58},"&",[32,1222,1223],{"class":66},"data)\n",[32,1225,1226],{"class":34,"line":94},[32,1227,52],{"emptyLinePlaceholder":51},[32,1229,1230,1233,1235,1238,1241,1244,1246,1249,1251],{"class":34,"line":100},[32,1231,1232],{"class":66},"    m ",[32,1234,106],{"class":58},[32,1236,1237],{"class":66}," data.(",[32,1239,1240],{"class":58},"map",[32,1242,1243],{"class":66},"[",[32,1245,112],{"class":58},[32,1247,1248],{"class":66},"]",[32,1250,79],{"class":62},[32,1252,255],{"class":66},[32,1254,1255,1258],{"class":34,"line":121},[32,1256,1257],{"class":38},"    \u002F\u002F count := m[\"count\"].(int)",[32,1259,1260],{"class":38},"  \u002F\u002F PANIC: interface is float64, not int\n",[32,1262,1263],{"class":34,"line":130},[32,1264,52],{"emptyLinePlaceholder":51},[32,1266,1267],{"class":34,"line":135},[32,1268,1269],{"class":38},"    \u002F\u002F ✅ Assert to float64, then convert:\n",[32,1271,1272,1275,1277,1279,1282,1285,1288,1290,1292],{"class":34,"line":141},[32,1273,1274],{"class":66},"    count ",[32,1276,106],{"class":58},[32,1278,431],{"class":58},[32,1280,1281],{"class":66},"(m[",[32,1283,1284],{"class":85},"\"count\"",[32,1286,1287],{"class":66},"].(",[32,1289,704],{"class":58},[32,1291,919],{"class":66},[32,1293,1294],{"class":38},"\u002F\u002F 42\n",[32,1296,1297,1300,1302,1305,1308,1310,1312,1315],{"class":34,"line":159},[32,1298,1299],{"class":66},"    price ",[32,1301,106],{"class":58},[32,1303,1304],{"class":66}," m[",[32,1306,1307],{"class":85},"\"price\"",[32,1309,1287],{"class":66},[32,1311,704],{"class":58},[32,1313,1314],{"class":66},")      ",[32,1316,1317],{"class":38},"\u002F\u002F 9.99\n",[32,1319,1320],{"class":34,"line":178},[32,1321,52],{"emptyLinePlaceholder":51},[32,1323,1324],{"class":34,"line":183},[32,1325,1326],{"class":38},"    \u002F\u002F ✅ Or use comma-ok to handle safely:\n",[32,1328,1329,1331,1334,1336,1338,1340,1342,1344],{"class":34,"line":189},[32,1330,192],{"class":58},[32,1332,1333],{"class":66}," f, ok ",[32,1335,106],{"class":58},[32,1337,1304],{"class":66},[32,1339,1284],{"class":85},[32,1341,1287],{"class":66},[32,1343,704],{"class":58},[32,1345,204],{"class":66},[32,1347,1348,1351,1353,1355],{"class":34,"line":207},[32,1349,1350],{"class":66},"        count ",[32,1352,106],{"class":58},[32,1354,431],{"class":58},[32,1356,1357],{"class":66},"(f)\n",[32,1359,1360,1362,1364],{"class":34,"line":231},[32,1361,787],{"class":66},[32,1363,790],{"class":58},[32,1365,1366],{"class":66}," count\n",[32,1368,1369],{"class":34,"line":243},[32,1370,261],{"class":66},[32,1372,1373],{"class":34,"line":258},[32,1374,267],{"class":66},[32,1376,1377],{"class":34,"line":264},[32,1378,52],{"emptyLinePlaceholder":51},[32,1380,1381],{"class":34,"line":270},[32,1382,1383],{"class":38},"\u002F\u002F ─── Better: use UseNumber for json.Number (string-backed) ───\n",[32,1385,1386,1388,1391],{"class":34,"line":275},[32,1387,59],{"class":58},[32,1389,1390],{"class":62}," jsonUseNumber",[32,1392,67],{"class":66},[32,1394,1395,1398,1400,1403,1406,1409,1411,1413,1416],{"class":34,"line":281},[32,1396,1397],{"class":66},"    dec ",[32,1399,106],{"class":58},[32,1401,1402],{"class":66}," json.",[32,1404,1405],{"class":62},"NewDecoder",[32,1407,1408],{"class":66},"(strings.",[32,1410,861],{"class":62},[32,1412,216],{"class":66},[32,1414,1415],{"class":85},"`{\"count\": 42}`",[32,1417,1418],{"class":66},"))\n",[32,1420,1421,1424,1427,1430],{"class":34,"line":287},[32,1422,1423],{"class":66},"    dec.",[32,1425,1426],{"class":62},"UseNumber",[32,1428,1429],{"class":66},"()  ",[32,1431,1432],{"class":38},"\u002F\u002F numbers become json.Number (a string)\n",[32,1434,1435,1437,1439],{"class":34,"line":293},[32,1436,73],{"class":58},[32,1438,1194],{"class":66},[32,1440,1197],{"class":62},[32,1442,1443,1445,1448,1450,1452],{"class":34,"line":299},[32,1444,1423],{"class":66},[32,1446,1447],{"class":62},"Decode",[32,1449,216],{"class":66},[32,1451,1220],{"class":58},[32,1453,1223],{"class":66},[32,1455,1456,1458,1460,1462,1464,1466,1468,1470,1472],{"class":34,"line":305},[32,1457,1232],{"class":66},[32,1459,106],{"class":58},[32,1461,1237],{"class":66},[32,1463,1240],{"class":58},[32,1465,1243],{"class":66},[32,1467,112],{"class":58},[32,1469,1248],{"class":66},[32,1471,79],{"class":62},[32,1473,255],{"class":66},[32,1475,1476,1479,1481,1483,1485,1487,1490,1492,1495,1498,1501,1503],{"class":34,"line":311},[32,1477,1478],{"class":66},"    n, _ ",[32,1480,106],{"class":58},[32,1482,1304],{"class":66},[32,1484,1284],{"class":85},[32,1486,1287],{"class":66},[32,1488,1489],{"class":62},"json",[32,1491,850],{"class":66},[32,1493,1494],{"class":62},"Number",[32,1496,1497],{"class":66},").",[32,1499,1500],{"class":62},"Int64",[32,1502,1429],{"class":66},[32,1504,1505],{"class":38},"\u002F\u002F parse as int64\n",[32,1507,1508,1511,1513,1516],{"class":34,"line":317},[32,1509,1510],{"class":66},"    fmt.",[32,1512,213],{"class":62},[32,1514,1515],{"class":66},"(n)  ",[32,1517,1294],{"class":38},[32,1519,1520],{"class":34,"line":323},[32,1521,267],{"class":66},[32,1523,1524],{"class":34,"line":329},[32,1525,52],{"emptyLinePlaceholder":51},[32,1527,1528],{"class":34,"line":335},[32,1529,1530],{"class":38},"\u002F\u002F ─── Best: unmarshal into a typed struct ───\n",[32,1532,1533,1535,1538,1541],{"class":34,"line":743},[32,1534,401],{"class":58},[32,1536,1537],{"class":62}," Product",[32,1539,1540],{"class":58}," struct",[32,1542,240],{"class":66},[32,1544,1545,1548,1550],{"class":34,"line":759},[32,1546,1547],{"class":66},"    Count ",[32,1549,169],{"class":58},[32,1551,1552],{"class":85},"     `json:\"count\"`\n",[32,1554,1555,1558,1560],{"class":34,"line":775},[32,1556,1557],{"class":66},"    Price ",[32,1559,704],{"class":58},[32,1561,1562],{"class":85}," `json:\"price\"`\n",[32,1564,1565],{"class":34,"line":784},[32,1566,267],{"class":66},[32,1568,1569,1571,1574],{"class":34,"line":796},[32,1570,59],{"class":58},[32,1572,1573],{"class":62}," jsonStruct",[32,1575,67],{"class":66},[32,1577,1578,1580,1583],{"class":34,"line":801},[32,1579,73],{"class":58},[32,1581,1582],{"class":66}," p ",[32,1584,1585],{"class":62},"Product\n",[32,1587,1589,1591,1593,1595,1597,1599,1601,1603,1605],{"class":34,"line":1588},40,[32,1590,1202],{"class":66},[32,1592,1205],{"class":62},[32,1594,909],{"class":66},[32,1596,503],{"class":58},[32,1598,216],{"class":66},[32,1600,1214],{"class":85},[32,1602,1217],{"class":66},[32,1604,1220],{"class":58},[32,1606,1607],{"class":66},"p)\n",[32,1609,1611,1613,1615,1618],{"class":34,"line":1610},41,[32,1612,1510],{"class":66},[32,1614,213],{"class":62},[32,1616,1617],{"class":66},"(p.Count)  ",[32,1619,1620],{"class":38},"\u002F\u002F 42 (int, not float64)\n",[32,1622,1624],{"class":34,"line":1623},42,[32,1625,267],{"class":66},[14,1627,1629],{"id":1628},"production-pattern-custom-unmarshaler","Production Pattern — Custom Unmarshaler",[19,1631,1632,1997,2001,2148,2152],{"language":21},[23,1633,1635],{"className":25,"code":1634,"language":21,"meta":27,"style":27},"\u002F\u002F When JSON has a polymorphic field (different types per key), implement\n\u002F\u002F json.Unmarshaler to handle the type dispatch cleanly.\n\ntype FlexibleValue struct {\n    StrVal   string\n    IntVal   int64\n    FloatVal float64\n    BoolVal  bool\n    IsNull   bool\n}\n\nfunc (f *FlexibleValue) UnmarshalJSON(data []byte) error {\n    data = bytes.TrimSpace(data)\n    if string(data) == \"null\" {\n        f.IsNull = true\n        return nil\n    }\n    if data[0] == '\"' {\n        return json.Unmarshal(data, &f.StrVal)\n    }\n    if data[0] == 't' || data[0] == 'f' {\n        return json.Unmarshal(data, &f.BoolVal)\n    }\n    \u002F\u002F Try int first, then float:\n    if i, err := strconv.ParseInt(string(data), 10, 64); err == nil {\n        f.IntVal = i\n        return nil\n    }\n    return json.Unmarshal(data, &f.FloatVal)\n}\n\n\u002F\u002F This avoids the float64-for-everything problem — you control the\n\u002F\u002F type inference instead of relying on json's default behavior.\n",[29,1636,1637,1642,1647,1651,1662,1670,1678,1686,1694,1701,1705,1709,1744,1759,1776,1786,1793,1797,1822,1838,1842,1881,1896,1900,1905,1944,1954,1960,1964,1979,1983,1987,1992],{"__ignoreMap":27},[32,1638,1639],{"class":34,"line":35},[32,1640,1641],{"class":38},"\u002F\u002F When JSON has a polymorphic field (different types per key), implement\n",[32,1643,1644],{"class":34,"line":42},[32,1645,1646],{"class":38},"\u002F\u002F json.Unmarshaler to handle the type dispatch cleanly.\n",[32,1648,1649],{"class":34,"line":48},[32,1650,52],{"emptyLinePlaceholder":51},[32,1652,1653,1655,1658,1660],{"class":34,"line":55},[32,1654,401],{"class":58},[32,1656,1657],{"class":62}," FlexibleValue",[32,1659,1540],{"class":58},[32,1661,240],{"class":66},[32,1663,1664,1667],{"class":34,"line":70},[32,1665,1666],{"class":66},"    StrVal   ",[32,1668,1669],{"class":58},"string\n",[32,1671,1672,1675],{"class":34,"line":89},[32,1673,1674],{"class":66},"    IntVal   ",[32,1676,1677],{"class":58},"int64\n",[32,1679,1680,1683],{"class":34,"line":94},[32,1681,1682],{"class":66},"    FloatVal ",[32,1684,1685],{"class":58},"float64\n",[32,1687,1688,1691],{"class":34,"line":100},[32,1689,1690],{"class":66},"    BoolVal  ",[32,1692,1693],{"class":58},"bool\n",[32,1695,1696,1699],{"class":34,"line":121},[32,1697,1698],{"class":66},"    IsNull   ",[32,1700,1693],{"class":58},[32,1702,1703],{"class":34,"line":130},[32,1704,267],{"class":66},[32,1706,1707],{"class":34,"line":135},[32,1708,52],{"emptyLinePlaceholder":51},[32,1710,1711,1713,1716,1719,1722,1725,1727,1730,1732,1734,1736,1738,1740,1742],{"class":34,"line":141},[32,1712,59],{"class":58},[32,1714,1715],{"class":66}," (",[32,1717,1718],{"class":375},"f ",[32,1720,1721],{"class":58},"*",[32,1723,1724],{"class":62},"FlexibleValue",[32,1726,382],{"class":66},[32,1728,1729],{"class":62},"UnmarshalJSON",[32,1731,216],{"class":66},[32,1733,1052],{"class":375},[32,1735,500],{"class":66},[32,1737,503],{"class":58},[32,1739,382],{"class":66},[32,1741,1061],{"class":58},[32,1743,240],{"class":66},[32,1745,1746,1749,1751,1754,1757],{"class":34,"line":159},[32,1747,1748],{"class":66},"    data ",[32,1750,790],{"class":58},[32,1752,1753],{"class":66}," bytes.",[32,1755,1756],{"class":62},"TrimSpace",[32,1758,1122],{"class":66},[32,1760,1761,1763,1765,1768,1771,1774],{"class":34,"line":178},[32,1762,192],{"class":58},[32,1764,467],{"class":58},[32,1766,1767],{"class":66},"(data) ",[32,1769,1770],{"class":58},"==",[32,1772,1773],{"class":85}," \"null\"",[32,1775,240],{"class":66},[32,1777,1778,1781,1783],{"class":34,"line":183},[32,1779,1780],{"class":66},"        f.IsNull ",[32,1782,790],{"class":58},[32,1784,1785],{"class":412}," true\n",[32,1787,1788,1790],{"class":34,"line":189},[32,1789,421],{"class":58},[32,1791,1792],{"class":412}," nil\n",[32,1794,1795],{"class":34,"line":207},[32,1796,261],{"class":66},[32,1798,1799,1801,1804,1807,1810,1812,1815,1817,1820],{"class":34,"line":231},[32,1800,192],{"class":58},[32,1802,1803],{"class":66}," data[",[32,1805,1806],{"class":412},"0",[32,1808,1809],{"class":66},"] ",[32,1811,1770],{"class":58},[32,1813,1814],{"class":85}," '",[32,1816,454],{"class":412},[32,1818,1819],{"class":85},"'",[32,1821,240],{"class":66},[32,1823,1824,1826,1828,1830,1833,1835],{"class":34,"line":243},[32,1825,421],{"class":58},[32,1827,1402],{"class":66},[32,1829,1205],{"class":62},[32,1831,1832],{"class":66},"(data, ",[32,1834,1220],{"class":58},[32,1836,1837],{"class":66},"f.StrVal)\n",[32,1839,1840],{"class":34,"line":258},[32,1841,261],{"class":66},[32,1843,1844,1846,1848,1850,1852,1854,1856,1859,1861,1864,1866,1868,1870,1872,1874,1877,1879],{"class":34,"line":264},[32,1845,192],{"class":58},[32,1847,1803],{"class":66},[32,1849,1806],{"class":412},[32,1851,1809],{"class":66},[32,1853,1770],{"class":58},[32,1855,1814],{"class":85},[32,1857,1858],{"class":412},"t",[32,1860,1819],{"class":85},[32,1862,1863],{"class":58}," ||",[32,1865,1803],{"class":66},[32,1867,1806],{"class":412},[32,1869,1809],{"class":66},[32,1871,1770],{"class":58},[32,1873,1814],{"class":85},[32,1875,1876],{"class":412},"f",[32,1878,1819],{"class":85},[32,1880,240],{"class":66},[32,1882,1883,1885,1887,1889,1891,1893],{"class":34,"line":270},[32,1884,421],{"class":58},[32,1886,1402],{"class":66},[32,1888,1205],{"class":62},[32,1890,1832],{"class":66},[32,1892,1220],{"class":58},[32,1894,1895],{"class":66},"f.BoolVal)\n",[32,1897,1898],{"class":34,"line":275},[32,1899,261],{"class":66},[32,1901,1902],{"class":34,"line":281},[32,1903,1904],{"class":38},"    \u002F\u002F Try int first, then float:\n",[32,1906,1907,1909,1912,1914,1917,1920,1922,1924,1927,1930,1932,1935,1938,1940,1942],{"class":34,"line":287},[32,1908,192],{"class":58},[32,1910,1911],{"class":66}," i, err ",[32,1913,106],{"class":58},[32,1915,1916],{"class":66}," strconv.",[32,1918,1919],{"class":62},"ParseInt",[32,1921,216],{"class":66},[32,1923,112],{"class":58},[32,1925,1926],{"class":66},"(data), ",[32,1928,1929],{"class":412},"10",[32,1931,222],{"class":66},[32,1933,1934],{"class":412},"64",[32,1936,1937],{"class":66},"); err ",[32,1939,1770],{"class":58},[32,1941,413],{"class":412},[32,1943,240],{"class":66},[32,1945,1946,1949,1951],{"class":34,"line":293},[32,1947,1948],{"class":66},"        f.IntVal ",[32,1950,790],{"class":58},[32,1952,1953],{"class":66}," i\n",[32,1955,1956,1958],{"class":34,"line":299},[32,1957,421],{"class":58},[32,1959,1792],{"class":412},[32,1961,1962],{"class":34,"line":305},[32,1963,261],{"class":66},[32,1965,1966,1968,1970,1972,1974,1976],{"class":34,"line":311},[32,1967,1127],{"class":58},[32,1969,1402],{"class":66},[32,1971,1205],{"class":62},[32,1973,1832],{"class":66},[32,1975,1220],{"class":58},[32,1977,1978],{"class":66},"f.FloatVal)\n",[32,1980,1981],{"class":34,"line":317},[32,1982,267],{"class":66},[32,1984,1985],{"class":34,"line":323},[32,1986,52],{"emptyLinePlaceholder":51},[32,1988,1989],{"class":34,"line":329},[32,1990,1991],{"class":38},"\u002F\u002F This avoids the float64-for-everything problem — you control the\n",[32,1993,1994],{"class":34,"line":335},[32,1995,1996],{"class":38},"\u002F\u002F type inference instead of relying on json's default behavior.\n",[14,1998,2000],{"id":1999},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2002,2003,2004,2015,2041,2067,2083,2099,2108,2129],"ul",{},[2005,2006,2007,2014],"li",{},[2008,2009,2010,2013],"strong",{},[29,2011,2012],{},"i.(T)"," panics on mismatch",": the single-value form. Use comma-ok unless a mismatch is a bug.",[2005,2016,2017,580,2026,2029,2030,2023,2032,2034,2035,2037,2038,2040],{},[2008,2018,2019,2020,2023,2024],{},"Multi-type case ",[29,2021,2022],{},"v"," is ",[29,2025,79],{},[29,2027,2028],{},"case int, string: ... v ..."," — ",[29,2031,2022],{},[29,2033,79],{},", not ",[29,2036,169],{}," or ",[29,2039,112],{},". Assert again inside the case.",[2005,2042,2043,580,2046,2049,2050,2052,2053,2056,2057,2060,2061,2063,2064,2066],{},[2008,2044,2045],{},"Assertion to pointer type",[29,2047,2048],{},"i.(*Dog)"," works if ",[29,2051,376],{}," holds a ",[29,2054,2055],{},"*Dog",". ",[29,2058,2059],{},"i.(Dog)"," fails if ",[29,2062,376],{}," holds ",[29,2065,2055],{}," (pointer ≠ value type).",[2005,2068,2069,580,2075,2078,2079,2082],{},[2008,2070,2071,2074],{},[29,2072,2073],{},"case nil"," matches nil interface",[29,2076,2077],{},"case nil:"," matches ",[29,2080,2081],{},"(type=nil, value=nil)",", NOT an interface wrapping a nil pointer. Handle both.",[2005,2084,2085,2091,2092,2094,2095,2098],{},[2008,2086,2087,2090],{},[29,2088,2089],{},"default"," is required for unknown types",": without ",[29,2093,2089],{},", an unrecognized type falls through silently. Add ",[29,2096,2097],{},"default:"," for safety.",[2005,2100,2101,580,2104,2107],{},[2008,2102,2103],{},"Type assertions don't work on non-interface types",[29,2105,2106],{},"var x int = 5; x.(int)"," is a compile error. Assertions are for interface values only.",[2005,2109,2110,580,2113,2116,2117,2119,2120,2122,2123,2125,2126,2128],{},[2008,2111,2112],{},"JSON numbers are float64",[29,2114,2115],{},"json.Unmarshal"," into ",[29,2118,79],{}," makes all numbers ",[29,2121,704],{},". Asserting to ",[29,2124,169],{}," panics. Use ",[29,2127,1426],{}," or typed structs.",[2005,2130,2131,580,2134,2137,2138,2140,2141,2143,2144,2147],{},[2008,2132,2133],{},"Assertion to an interface the type doesn't satisfy",[29,2135,2136],{},"i.(io.Writer)"," where ",[29,2139,376],{},"'s type doesn't have ",[29,2142,906],{}," → ",[29,2145,2146],{},"ok = false"," (comma-ok) or panic (single-value).",[14,2149,2151],{"id":2150},"quick-quiz","🧠 Quick Quiz",[19,2153,2154,2274],{"language":21},[23,2155,2157],{"className":25,"code":2156,"language":21,"meta":27,"style":27},"func process(i any) {\n    switch v := i.(type) {\n    case nil:\n        fmt.Println(\"nil\")\n    case int, string:\n        fmt.Println(\"int or string:\", v)\n    case string:\n        fmt.Println(\"string:\", v)\n    }\n}\nprocess(\"hello\")\n",[29,2158,2159,2174,2188,2196,2209,2221,2234,2242,2255,2259,2263],{"__ignoreMap":27},[32,2160,2161,2163,2166,2168,2170,2172],{"class":34,"line":35},[32,2162,59],{"class":58},[32,2164,2165],{"class":62}," process",[32,2167,216],{"class":66},[32,2169,376],{"class":375},[32,2171,379],{"class":62},[32,2173,404],{"class":66},[32,2175,2176,2178,2180,2182,2184,2186],{"class":34,"line":42},[32,2177,391],{"class":58},[32,2179,394],{"class":66},[32,2181,106],{"class":58},[32,2183,109],{"class":66},[32,2185,401],{"class":58},[32,2187,404],{"class":66},[32,2189,2190,2192,2194],{"class":34,"line":48},[32,2191,409],{"class":58},[32,2193,413],{"class":412},[32,2195,416],{"class":66},[32,2197,2198,2200,2202,2204,2207],{"class":34,"line":55},[32,2199,210],{"class":66},[32,2201,213],{"class":62},[32,2203,216],{"class":66},[32,2205,2206],{"class":85},"\"nil\"",[32,2208,255],{"class":66},[32,2210,2211,2213,2215,2217,2219],{"class":34,"line":70},[32,2212,409],{"class":58},[32,2214,431],{"class":58},[32,2216,222],{"class":66},[32,2218,112],{"class":58},[32,2220,416],{"class":66},[32,2222,2223,2225,2227,2229,2232],{"class":34,"line":89},[32,2224,210],{"class":66},[32,2226,213],{"class":62},[32,2228,216],{"class":66},[32,2230,2231],{"class":85},"\"int or string:\"",[32,2233,692],{"class":66},[32,2235,2236,2238,2240],{"class":34,"line":94},[32,2237,409],{"class":58},[32,2239,467],{"class":58},[32,2241,416],{"class":66},[32,2243,2244,2246,2248,2250,2253],{"class":34,"line":100},[32,2245,210],{"class":66},[32,2247,213],{"class":62},[32,2249,216],{"class":66},[32,2251,2252],{"class":85},"\"string:\"",[32,2254,692],{"class":66},[32,2256,2257],{"class":34,"line":121},[32,2258,261],{"class":66},[32,2260,2261],{"class":34,"line":130},[32,2262,267],{"class":66},[32,2264,2265,2268,2270,2272],{"class":34,"line":135},[32,2266,2267],{"class":62},"process",[32,2269,216],{"class":66},[32,2271,866],{"class":85},[32,2273,255],{"class":66},[2275,2276,2277],"p",{},"What's printed?",[2279,2280,2281,2285,2293,2307,2325],"details",{},[2282,2283,2284],"summary",{},"Answer",[23,2286,2291],{"className":2287,"code":2289,"language":2290},[2288],"language-text","int or string: hello\n","text",[29,2292,2289],{"__ignoreMap":27},[2275,2294,2295,2296,2299,2300,2303,2304,2306],{},"The ",[29,2297,2298],{},"case int, string:"," matches FIRST (it comes before ",[29,2301,2302],{},"case string:","). In a type switch, the FIRST matching case wins — cases are checked top to bottom. The ",[29,2305,2302],{}," below is unreachable (shadowed).",[2275,2308,2309,2311,2312,2314,2315,2317,2318,2321,2322,850],{},[29,2310,2022],{}," in the ",[29,2313,2298],{}," block is ",[29,2316,79],{}," (since it could be either), so ",[29,2319,2320],{},"fmt.Println(\"int or string:\", v)"," prints the value with default formatting: ",[29,2323,2324],{},"hello",[2275,2326,2327,2330,2331,2334],{},[2008,2328,2329],{},"The lesson",": type switch cases are checked in order. If a multi-type case comes before a specific case for one of those types, the specific case is unreachable. Put specific cases first, or remove the overlap. ",[29,2332,2333],{},"go vet"," and linters can flag unreachable cases.",[14,2336,2338],{"id":2337},"whats-next","📚 What's Next",[2275,2340,2341,2342,2347,2348,222,2351,2354,2355,2358,2359,2362],{},"→ ",[2343,2344,2346],"a",{"href":2345},"\u002Fgo\u002F14-generics","14 — Generics"," — type parameters, constraints, ",[29,2349,2350],{},"cmp.Ordered",[29,2352,2353],{},"~T"," underlying-type matching, and the ",[29,2356,2357],{},"slices","\u002F",[29,2360,2361],{},"maps"," packages.",[2364,2365,2366],"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 .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}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}",{"title":27,"searchDepth":42,"depth":42,"links":2368},[2369,2370,2371],{"id":16,"depth":42,"text":17},{"id":341,"depth":42,"text":342},{"id":2337,"depth":42,"text":2338},"Comma-ok assertions, type switch dispatch, interface-to-interface capability checks, JSON float64 traps, and panic-safe patterns.","md",{},"\u002Fgo\u002F13-type-assertions-and-switches",{"title":5,"description":2372},"go\u002F13-type-assertions-and-switches","6cg3m_JNLHc-XELS9ug4zlvUAAW4WffVzClEVYC3XS8",1789924648525]