[{"data":1,"prerenderedAt":3223},["ShallowReactive",2],{"page-\u002Fgo\u002F02-hello-world-and-go-command":3},{"id":4,"title":5,"body":6,"description":3216,"extension":3217,"meta":3218,"navigation":225,"path":3219,"seo":3220,"stem":3221,"__hash__":3222},"content\u002Fgo\u002F02-hello-world-and-go-command.md","02 — Package Anatomy & the go Command",{"type":7,"value":8,"toc":3193},"minimark",[9,13,26,31,152,157,357,361,711,715,780,784,890,896,1248,1255,1645,1649,1767,1771,1881,1894,2061,2355,2437,2513,2517,2709,2713,2814,2818,3012,3016,3118,3121,3172,3176,3189],[10,11,5],"h1",{"id":12},"_02-package-anatomy-the-go-command",[14,15,16,17,21,22,25],"p",{},"This chapter goes into package mechanics, the compiler\u002Flinker pipeline, ",[18,19,20],"code",{},"init()"," execution order, and the ",[18,23,24],{},"go"," subcommands you use daily in production.",[27,28,30],"h2",{"id":29},"the-compilation-pipeline","The Compilation Pipeline",[32,33,34],"code-wrapper",{"language":24},[35,36,40],"pre",{"className":37,"code":38,"language":24,"meta":39,"style":39},"language-go shiki shiki-themes github-light github-dark","\u002F\u002F ┌─────────────────────────────────────────────────────────────────────┐\n\u002F\u002F │  source.go                                                         │\n\u002F\u002F │    ↓ go tool compile (per package, parallel)                       │\n\u002F\u002F │  source.o (object file) + source.a (archive)                      │\n\u002F\u002F │    ↓ go tool link (single-threaded, deduplicates archives)         │\n\u002F\u002F │  binary (ELF on linux, Mach-O on darwin, PE on windows)            │\n\u002F\u002F │    ↓ runtime boots: scheduler, GC, stack growth, netpoller         │\n\u002F\u002F │  main.main() runs                                                  │\n\u002F\u002F └─────────────────────────────────────────────────────────────────────┘\n\u002F\u002F\n\u002F\u002F The compiler is split into phases:\n\u002F\u002F   1. Parse (go\u002Fscanner → go\u002Fparser → AST)\n\u002F\u002F   2. Type check (go\u002Ftypes — resolves types, checks assignments)\n\u002F\u002F   3. SSA (Static Single Assignment — optimization IR)\n\u002F\u002F   4. Code generation (machine code per GOARCH)\n\u002F\u002F\n\u002F\u002F Inter-package dependencies are compiled in topological order.\n\u002F\u002F Circular imports are detected in phase 2 → compile error.\n","",[18,41,42,51,57,63,69,75,81,87,93,99,105,111,117,123,129,135,140,146],{"__ignoreMap":39},[43,44,47],"span",{"class":45,"line":46},"line",1,[43,48,50],{"class":49},"sdCPZ","\u002F\u002F ┌─────────────────────────────────────────────────────────────────────┐\n",[43,52,54],{"class":45,"line":53},2,[43,55,56],{"class":49},"\u002F\u002F │  source.go                                                         │\n",[43,58,60],{"class":45,"line":59},3,[43,61,62],{"class":49},"\u002F\u002F │    ↓ go tool compile (per package, parallel)                       │\n",[43,64,66],{"class":45,"line":65},4,[43,67,68],{"class":49},"\u002F\u002F │  source.o (object file) + source.a (archive)                      │\n",[43,70,72],{"class":45,"line":71},5,[43,73,74],{"class":49},"\u002F\u002F │    ↓ go tool link (single-threaded, deduplicates archives)         │\n",[43,76,78],{"class":45,"line":77},6,[43,79,80],{"class":49},"\u002F\u002F │  binary (ELF on linux, Mach-O on darwin, PE on windows)            │\n",[43,82,84],{"class":45,"line":83},7,[43,85,86],{"class":49},"\u002F\u002F │    ↓ runtime boots: scheduler, GC, stack growth, netpoller         │\n",[43,88,90],{"class":45,"line":89},8,[43,91,92],{"class":49},"\u002F\u002F │  main.main() runs                                                  │\n",[43,94,96],{"class":45,"line":95},9,[43,97,98],{"class":49},"\u002F\u002F └─────────────────────────────────────────────────────────────────────┘\n",[43,100,102],{"class":45,"line":101},10,[43,103,104],{"class":49},"\u002F\u002F\n",[43,106,108],{"class":45,"line":107},11,[43,109,110],{"class":49},"\u002F\u002F The compiler is split into phases:\n",[43,112,114],{"class":45,"line":113},12,[43,115,116],{"class":49},"\u002F\u002F   1. Parse (go\u002Fscanner → go\u002Fparser → AST)\n",[43,118,120],{"class":45,"line":119},13,[43,121,122],{"class":49},"\u002F\u002F   2. Type check (go\u002Ftypes — resolves types, checks assignments)\n",[43,124,126],{"class":45,"line":125},14,[43,127,128],{"class":49},"\u002F\u002F   3. SSA (Static Single Assignment — optimization IR)\n",[43,130,132],{"class":45,"line":131},15,[43,133,134],{"class":49},"\u002F\u002F   4. Code generation (machine code per GOARCH)\n",[43,136,138],{"class":45,"line":137},16,[43,139,104],{"class":49},[43,141,143],{"class":45,"line":142},17,[43,144,145],{"class":49},"\u002F\u002F Inter-package dependencies are compiled in topological order.\n",[43,147,149],{"class":45,"line":148},18,[43,150,151],{"class":49},"\u002F\u002F Circular imports are detected in phase 2 → compile error.\n",[153,154,156],"h3",{"id":155},"examining-the-binary","Examining the binary",[32,158,160],{"language":159},"bash",[35,161,164],{"className":162,"code":163,"language":159,"meta":39,"style":39},"language-bash shiki shiki-themes github-light github-dark","# What's inside the binary?\ngo tool nm bin\u002Fmyapp | head                  # list all symbols\ngo tool nm bin\u002Fmyapp | grep -c 'runtime\\.'   # count runtime symbols\n\n# Disassemble a function (reads the binary, not source):\ngo tool objdump -s 'main\\.runServer' bin\u002Fmyapp\n\n# Check if a binary is statically linked (no dynamic deps):\nfile bin\u002Fmyapp\n# bin\u002Fmyapp: ELF 64-bit LSB executable, x86-64, statically linked, ...\n\n# List dynamic dependencies (should be empty for CGO_ENABLED=0):\nldd bin\u002Fmyapp 2>&1\n# not a dynamic executable\n\n# Build info — module versions embedded in the binary:\ngo version -m bin\u002Fmyapp\n#   go1.22.0\n#   path    example.com\u002Fmyapp\n#   mod     github.com\u002Flib\u002Fpq  v1.10.0\n#   dep     golang.org\u002Fx\u002Fnet   v0.20.0\n#   build   -trimpath          (build flag)\n#   build   CGO_ENABLED=0\n#   build   GOOS=linux\n",[18,165,166,171,196,221,227,232,250,254,259,266,271,275,280,290,295,299,304,316,321,327,333,339,345,351],{"__ignoreMap":39},[43,167,168],{"class":45,"line":46},[43,169,170],{"class":49},"# What's inside the binary?\n",[43,172,173,176,180,183,186,190,193],{"class":45,"line":53},[43,174,24],{"class":175},"sIsaT",[43,177,179],{"class":178},"sJ6F3"," tool",[43,181,182],{"class":178}," nm",[43,184,185],{"class":178}," bin\u002Fmyapp",[43,187,189],{"class":188},"svdQ7"," |",[43,191,192],{"class":175}," head",[43,194,195],{"class":49},"                  # list all symbols\n",[43,197,198,200,202,204,206,208,211,215,218],{"class":45,"line":59},[43,199,24],{"class":175},[43,201,179],{"class":178},[43,203,182],{"class":178},[43,205,185],{"class":178},[43,207,189],{"class":188},[43,209,210],{"class":175}," grep",[43,212,214],{"class":213},"snvgF"," -c",[43,216,217],{"class":178}," 'runtime\\.'",[43,219,220],{"class":49},"   # count runtime symbols\n",[43,222,223],{"class":45,"line":65},[43,224,226],{"emptyLinePlaceholder":225},true,"\n",[43,228,229],{"class":45,"line":71},[43,230,231],{"class":49},"# Disassemble a function (reads the binary, not source):\n",[43,233,234,236,238,241,244,247],{"class":45,"line":77},[43,235,24],{"class":175},[43,237,179],{"class":178},[43,239,240],{"class":178}," objdump",[43,242,243],{"class":213}," -s",[43,245,246],{"class":178}," 'main\\.runServer'",[43,248,249],{"class":178}," bin\u002Fmyapp\n",[43,251,252],{"class":45,"line":83},[43,253,226],{"emptyLinePlaceholder":225},[43,255,256],{"class":45,"line":89},[43,257,258],{"class":49},"# Check if a binary is statically linked (no dynamic deps):\n",[43,260,261,264],{"class":45,"line":95},[43,262,263],{"class":175},"file",[43,265,249],{"class":178},[43,267,268],{"class":45,"line":101},[43,269,270],{"class":49},"# bin\u002Fmyapp: ELF 64-bit LSB executable, x86-64, statically linked, ...\n",[43,272,273],{"class":45,"line":107},[43,274,226],{"emptyLinePlaceholder":225},[43,276,277],{"class":45,"line":113},[43,278,279],{"class":49},"# List dynamic dependencies (should be empty for CGO_ENABLED=0):\n",[43,281,282,285,287],{"class":45,"line":119},[43,283,284],{"class":175},"ldd",[43,286,185],{"class":178},[43,288,289],{"class":188}," 2>&1\n",[43,291,292],{"class":45,"line":125},[43,293,294],{"class":49},"# not a dynamic executable\n",[43,296,297],{"class":45,"line":131},[43,298,226],{"emptyLinePlaceholder":225},[43,300,301],{"class":45,"line":137},[43,302,303],{"class":49},"# Build info — module versions embedded in the binary:\n",[43,305,306,308,311,314],{"class":45,"line":142},[43,307,24],{"class":175},[43,309,310],{"class":178}," version",[43,312,313],{"class":213}," -m",[43,315,249],{"class":178},[43,317,318],{"class":45,"line":148},[43,319,320],{"class":49},"#   go1.22.0\n",[43,322,324],{"class":45,"line":323},19,[43,325,326],{"class":49},"#   path    example.com\u002Fmyapp\n",[43,328,330],{"class":45,"line":329},20,[43,331,332],{"class":49},"#   mod     github.com\u002Flib\u002Fpq  v1.10.0\n",[43,334,336],{"class":45,"line":335},21,[43,337,338],{"class":49},"#   dep     golang.org\u002Fx\u002Fnet   v0.20.0\n",[43,340,342],{"class":45,"line":341},22,[43,343,344],{"class":49},"#   build   -trimpath          (build flag)\n",[43,346,348],{"class":45,"line":347},23,[43,349,350],{"class":49},"#   build   CGO_ENABLED=0\n",[43,352,354],{"class":45,"line":353},24,[43,355,356],{"class":49},"#   build   GOOS=linux\n",[27,358,360],{"id":359},"package-anatomy","Package Anatomy",[32,362,363],{"language":24},[35,364,366],{"className":37,"code":365,"language":24,"meta":39,"style":39},"\u002F\u002F A package = all .go files in one directory with the same `package` clause.\n\u002F\u002F Internal structure conventions:\n\n\u002F\u002F ---- exported.go ----\npackage user                       \u002F\u002F package name (matches last import path segment)\n\nimport (                           \u002F\u002F imports grouped: stdlib, blank line, third-party\n    \"context\"\n    \"database\u002Fsql\"\n    \"errors\"\n\n    \"github.com\u002Flib\u002Fpq\"\n)\n\n\u002F\u002F Exported types (PascalCase) — visible to importers.\ntype User struct {\n    ID    int64\n    Email string\n}\n\n\u002F\u002F Exported function.\nfunc Fetch(ctx context.Context, db *sql.DB, id int64) (*User, error) {\n    \u002F\u002F ...\n    return &User{}, nil\n}\n\n\u002F\u002F ---- internal.go ---- (same package, same directory)\npackage user\n\nvar errNotFound = errors.New(\"user: not found\")   \u002F\u002F unexported — package-private\n\nfunc validateEmail(s string) bool {                \u002F\u002F unexported\n    return s != \"\"\n}\n",[18,367,368,373,378,382,387,398,402,414,425,434,443,447,456,461,465,470,484,492,500,505,509,514,580,585,601,606,611,617,625,630,659,664,692,706],{"__ignoreMap":39},[43,369,370],{"class":45,"line":46},[43,371,372],{"class":49},"\u002F\u002F A package = all .go files in one directory with the same `package` clause.\n",[43,374,375],{"class":45,"line":53},[43,376,377],{"class":49},"\u002F\u002F Internal structure conventions:\n",[43,379,380],{"class":45,"line":59},[43,381,226],{"emptyLinePlaceholder":225},[43,383,384],{"class":45,"line":65},[43,385,386],{"class":49},"\u002F\u002F ---- exported.go ----\n",[43,388,389,392,395],{"class":45,"line":71},[43,390,391],{"class":188},"package",[43,393,394],{"class":175}," user",[43,396,397],{"class":49},"                       \u002F\u002F package name (matches last import path segment)\n",[43,399,400],{"class":45,"line":77},[43,401,226],{"emptyLinePlaceholder":225},[43,403,404,407,411],{"class":45,"line":83},[43,405,406],{"class":188},"import",[43,408,410],{"class":409},"ssxIu"," (                           ",[43,412,413],{"class":49},"\u002F\u002F imports grouped: stdlib, blank line, third-party\n",[43,415,416,419,422],{"class":45,"line":89},[43,417,418],{"class":178},"    \"",[43,420,421],{"class":175},"context",[43,423,424],{"class":178},"\"\n",[43,426,427,429,432],{"class":45,"line":95},[43,428,418],{"class":178},[43,430,431],{"class":175},"database\u002Fsql",[43,433,424],{"class":178},[43,435,436,438,441],{"class":45,"line":101},[43,437,418],{"class":178},[43,439,440],{"class":175},"errors",[43,442,424],{"class":178},[43,444,445],{"class":45,"line":107},[43,446,226],{"emptyLinePlaceholder":225},[43,448,449,451,454],{"class":45,"line":113},[43,450,418],{"class":178},[43,452,453],{"class":175},"github.com\u002Flib\u002Fpq",[43,455,424],{"class":178},[43,457,458],{"class":45,"line":119},[43,459,460],{"class":409},")\n",[43,462,463],{"class":45,"line":125},[43,464,226],{"emptyLinePlaceholder":225},[43,466,467],{"class":45,"line":131},[43,468,469],{"class":49},"\u002F\u002F Exported types (PascalCase) — visible to importers.\n",[43,471,472,475,478,481],{"class":45,"line":137},[43,473,474],{"class":188},"type",[43,476,477],{"class":175}," User",[43,479,480],{"class":188}," struct",[43,482,483],{"class":409}," {\n",[43,485,486,489],{"class":45,"line":142},[43,487,488],{"class":409},"    ID    ",[43,490,491],{"class":188},"int64\n",[43,493,494,497],{"class":45,"line":148},[43,495,496],{"class":409},"    Email ",[43,498,499],{"class":188},"string\n",[43,501,502],{"class":45,"line":323},[43,503,504],{"class":409},"}\n",[43,506,507],{"class":45,"line":329},[43,508,226],{"emptyLinePlaceholder":225},[43,510,511],{"class":45,"line":335},[43,512,513],{"class":49},"\u002F\u002F Exported function.\n",[43,515,516,519,522,525,529,532,535,538,541,544,547,550,552,555,557,560,563,566,569,572,574,577],{"class":45,"line":341},[43,517,518],{"class":188},"func",[43,520,521],{"class":175}," Fetch",[43,523,524],{"class":409},"(",[43,526,528],{"class":527},"sCrzJ","ctx",[43,530,531],{"class":175}," context",[43,533,534],{"class":409},".",[43,536,537],{"class":175},"Context",[43,539,540],{"class":409},", ",[43,542,543],{"class":527},"db",[43,545,546],{"class":188}," *",[43,548,549],{"class":175},"sql",[43,551,534],{"class":409},[43,553,554],{"class":175},"DB",[43,556,540],{"class":409},[43,558,559],{"class":527},"id",[43,561,562],{"class":188}," int64",[43,564,565],{"class":409},") (",[43,567,568],{"class":188},"*",[43,570,571],{"class":175},"User",[43,573,540],{"class":409},[43,575,576],{"class":188},"error",[43,578,579],{"class":409},") {\n",[43,581,582],{"class":45,"line":347},[43,583,584],{"class":49},"    \u002F\u002F ...\n",[43,586,587,590,593,595,598],{"class":45,"line":353},[43,588,589],{"class":188},"    return",[43,591,592],{"class":188}," &",[43,594,571],{"class":175},[43,596,597],{"class":409},"{}, ",[43,599,600],{"class":213},"nil\n",[43,602,604],{"class":45,"line":603},25,[43,605,504],{"class":409},[43,607,609],{"class":45,"line":608},26,[43,610,226],{"emptyLinePlaceholder":225},[43,612,614],{"class":45,"line":613},27,[43,615,616],{"class":49},"\u002F\u002F ---- internal.go ---- (same package, same directory)\n",[43,618,620,622],{"class":45,"line":619},28,[43,621,391],{"class":188},[43,623,624],{"class":175}," user\n",[43,626,628],{"class":45,"line":627},29,[43,629,226],{"emptyLinePlaceholder":225},[43,631,633,636,639,642,645,648,650,653,656],{"class":45,"line":632},30,[43,634,635],{"class":188},"var",[43,637,638],{"class":409}," errNotFound ",[43,640,641],{"class":188},"=",[43,643,644],{"class":409}," errors.",[43,646,647],{"class":175},"New",[43,649,524],{"class":409},[43,651,652],{"class":178},"\"user: not found\"",[43,654,655],{"class":409},")   ",[43,657,658],{"class":49},"\u002F\u002F unexported — package-private\n",[43,660,662],{"class":45,"line":661},31,[43,663,226],{"emptyLinePlaceholder":225},[43,665,667,669,672,674,677,680,683,686,689],{"class":45,"line":666},32,[43,668,518],{"class":188},[43,670,671],{"class":175}," validateEmail",[43,673,524],{"class":409},[43,675,676],{"class":527},"s",[43,678,679],{"class":188}," string",[43,681,682],{"class":409},") ",[43,684,685],{"class":188},"bool",[43,687,688],{"class":409}," {                ",[43,690,691],{"class":49},"\u002F\u002F unexported\n",[43,693,695,697,700,703],{"class":45,"line":694},33,[43,696,589],{"class":188},[43,698,699],{"class":409}," s ",[43,701,702],{"class":188},"!=",[43,704,705],{"class":178}," \"\"\n",[43,707,709],{"class":45,"line":708},34,[43,710,504],{"class":409},[153,712,714],{"id":713},"package-naming-rules","Package naming rules",[32,716,717],{"language":24},[35,718,720],{"className":37,"code":719,"language":24,"meta":39,"style":39},"\u002F\u002F The package name should be:\n\u002F\u002F   - short, lowercase, single word (no underscores, no mixedCase)\n\u002F\u002F   - NOT \"util\", \"common\", \"helpers\" (too generic — what's inside?)\n\u002F\u002F   - NOT the same as a common variable name (avoids shadowing)\n\u002F\u002F\n\u002F\u002F Good:   user, httpclient, ratelimiter, config, migrator\n\u002F\u002F Bad:    util, common, lib, myPackage, data_structures\n\n\u002F\u002F Import path vs package name can differ — but shouldn't:\n\u002F\u002F   import \"github.com\u002Fx\u002Fy\u002Fuser\"   →  package user ✅\n\u002F\u002F   import \"github.com\u002Fx\u002Fy\u002Fusers\"  →  package user ✅ (path plural, name singular)\n\u002F\u002F   import \"github.com\u002Fx\u002Fy\u002Ffoo\"    →  package bar   ❌ (confusing — rename)\n",[18,721,722,727,732,737,742,746,751,756,760,765,770,775],{"__ignoreMap":39},[43,723,724],{"class":45,"line":46},[43,725,726],{"class":49},"\u002F\u002F The package name should be:\n",[43,728,729],{"class":45,"line":53},[43,730,731],{"class":49},"\u002F\u002F   - short, lowercase, single word (no underscores, no mixedCase)\n",[43,733,734],{"class":45,"line":59},[43,735,736],{"class":49},"\u002F\u002F   - NOT \"util\", \"common\", \"helpers\" (too generic — what's inside?)\n",[43,738,739],{"class":45,"line":65},[43,740,741],{"class":49},"\u002F\u002F   - NOT the same as a common variable name (avoids shadowing)\n",[43,743,744],{"class":45,"line":71},[43,745,104],{"class":49},[43,747,748],{"class":45,"line":77},[43,749,750],{"class":49},"\u002F\u002F Good:   user, httpclient, ratelimiter, config, migrator\n",[43,752,753],{"class":45,"line":83},[43,754,755],{"class":49},"\u002F\u002F Bad:    util, common, lib, myPackage, data_structures\n",[43,757,758],{"class":45,"line":89},[43,759,226],{"emptyLinePlaceholder":225},[43,761,762],{"class":45,"line":95},[43,763,764],{"class":49},"\u002F\u002F Import path vs package name can differ — but shouldn't:\n",[43,766,767],{"class":45,"line":101},[43,768,769],{"class":49},"\u002F\u002F   import \"github.com\u002Fx\u002Fy\u002Fuser\"   →  package user ✅\n",[43,771,772],{"class":45,"line":107},[43,773,774],{"class":49},"\u002F\u002F   import \"github.com\u002Fx\u002Fy\u002Fusers\"  →  package user ✅ (path plural, name singular)\n",[43,776,777],{"class":45,"line":113},[43,778,779],{"class":49},"\u002F\u002F   import \"github.com\u002Fx\u002Fy\u002Ffoo\"    →  package bar   ❌ (confusing — rename)\n",[153,781,783],{"id":782},"import-aliases","Import aliases",[32,785,786],{"language":24},[35,787,789],{"className":37,"code":788,"language":24,"meta":39,"style":39},"import (\n    \u002F\u002F Alias when the package name collides or is unclear:\n    stdjson \"encoding\u002Fjson\"          \u002F\u002F stdjson.Marshal — avoids collision with a var\n    _ \"github.com\u002Flib\u002Fpq\"            \u002F\u002F blank import — runs init() for side effects only\n    . \"github.com\u002Fstretchr\u002Ftestify\u002Fassert\"  \u002F\u002F dot import — assert.Equal(t, ...) (tests only!)\n)\n\n\u002F\u002F Blank import pattern — registers a database\u002Fsql driver:\n\u002F\u002F   import _ \"github.com\u002Flib\u002Fpq\"\n\u002F\u002F pq's init() calls sql.Register(\"postgres\", &Driver{}), making it available\n\u002F\u002F to sql.Open(\"postgres\", ...) without referencing pq directly.\n\n\u002F\u002F Dot import — DANGEROUS in production code (pollutes namespace, unclear origin).\n\u002F\u002F Acceptable ONLY in test files for assertion libraries.\n",[18,790,791,798,803,819,833,848,852,856,861,866,871,876,880,885],{"__ignoreMap":39},[43,792,793,795],{"class":45,"line":46},[43,794,406],{"class":188},[43,796,797],{"class":409}," (\n",[43,799,800],{"class":45,"line":53},[43,801,802],{"class":49},"    \u002F\u002F Alias when the package name collides or is unclear:\n",[43,804,805,808,811,814,816],{"class":45,"line":59},[43,806,807],{"class":409},"    stdjson ",[43,809,810],{"class":178},"\"",[43,812,813],{"class":175},"encoding\u002Fjson",[43,815,810],{"class":178},[43,817,818],{"class":49},"          \u002F\u002F stdjson.Marshal — avoids collision with a var\n",[43,820,821,824,826,828,830],{"class":45,"line":65},[43,822,823],{"class":409},"    _ ",[43,825,810],{"class":178},[43,827,453],{"class":175},[43,829,810],{"class":178},[43,831,832],{"class":49},"            \u002F\u002F blank import — runs init() for side effects only\n",[43,834,835,838,840,843,845],{"class":45,"line":71},[43,836,837],{"class":409},"    . ",[43,839,810],{"class":178},[43,841,842],{"class":175},"github.com\u002Fstretchr\u002Ftestify\u002Fassert",[43,844,810],{"class":178},[43,846,847],{"class":49},"  \u002F\u002F dot import — assert.Equal(t, ...) (tests only!)\n",[43,849,850],{"class":45,"line":77},[43,851,460],{"class":409},[43,853,854],{"class":45,"line":83},[43,855,226],{"emptyLinePlaceholder":225},[43,857,858],{"class":45,"line":89},[43,859,860],{"class":49},"\u002F\u002F Blank import pattern — registers a database\u002Fsql driver:\n",[43,862,863],{"class":45,"line":95},[43,864,865],{"class":49},"\u002F\u002F   import _ \"github.com\u002Flib\u002Fpq\"\n",[43,867,868],{"class":45,"line":101},[43,869,870],{"class":49},"\u002F\u002F pq's init() calls sql.Register(\"postgres\", &Driver{}), making it available\n",[43,872,873],{"class":45,"line":107},[43,874,875],{"class":49},"\u002F\u002F to sql.Open(\"postgres\", ...) without referencing pq directly.\n",[43,877,878],{"class":45,"line":113},[43,879,226],{"emptyLinePlaceholder":225},[43,881,882],{"class":45,"line":119},[43,883,884],{"class":49},"\u002F\u002F Dot import — DANGEROUS in production code (pollutes namespace, unclear origin).\n",[43,886,887],{"class":45,"line":125},[43,888,889],{"class":49},"\u002F\u002F Acceptable ONLY in test files for assertion libraries.\n",[27,891,893,895],{"id":892},"init-execution-order-and-why-its-dangerous",[18,894,20],{}," — Execution Order and Why It's Dangerous",[32,897,898],{"language":24},[35,899,901],{"className":37,"code":900,"language":24,"meta":39,"style":39},"\u002F\u002F ┌─────────────────────────────────────────────────────────────────────┐\n\u002F\u002F │ init() execution order (guaranteed by the runtime):                │\n\u002F\u002F │   1. All imported packages' init()s run first (depth-first)        │\n\u002F\u002F │   2. Package-level var initializers run (in declaration order)     │\n\u002F\u002F │   3. All init() functions in THIS package run (in file order,      │\n\u002F\u002F │      then declaration order within a file)                         │\n\u002F\u002F │   4. main() runs                                                   │\n\u002F\u002F │                                                                    │\n\u002F\u002F │ ⚠️ Cross-file init() order = alphabetical by filename (not         │\n\u002F\u002F │    guaranteed by spec, but this is what the toolchain does).       │\n\u002F\u002F │    NEVER rely on cross-file init() order — merge into one init()   │\n\u002F\u002F │    if order matters.                                               │\n\u002F\u002F └─────────────────────────────────────────────────────────────────────┘\n\npackage database\n\nvar (\n    pool    *ConnectionPool    \u002F\u002F initialized in init()\n    driver  string\n)\n\nfunc init() {\n    \u002F\u002F Runs ONCE per process, after package vars, before main.\n    \u002F\u002F Multiple init()s per file are allowed (run in order).\n    pool = NewConnectionPool(10)\n    driver = \"postgres\"\n}\n\nfunc init() {\n    \u002F\u002F Second init() in same file — runs after the one above.\n    if pool == nil {\n        panic(\"database: pool not initialized\")  \u002F\u002F fail fast at startup\n    }\n}\n\n\u002F\u002F ❌ ANTI-PATTERN: init() doing I\u002FO (file reads, network calls)\n\u002F\u002F func init() {\n\u002F\u002F     data, _ := os.ReadFile(\"config.yaml\")  \u002F\u002F no error handling, no context\n\u002F\u002F     config = parseYaml(data)\n\u002F\u002F }\n\u002F\u002F Problems: untestable, no error propagation, blocks startup, no way to\n\u002F\u002F pass a different config in tests.\n\n\u002F\u002F ✅ CORRECT: explicit initialization function called from main()\nfunc Init(cfg Config) error {\n    var err error\n    pool, err = NewConnectionPool(cfg.PoolSize)\n    return err  \u002F\u002F caller handles the error\n}\n",[18,902,903,907,912,917,922,927,932,937,942,947,952,957,962,966,970,977,981,987,1000,1007,1011,1015,1025,1030,1035,1052,1062,1066,1070,1078,1083,1099,1115,1120,1124,1129,1135,1141,1150,1156,1162,1168,1174,1179,1185,1207,1219,1232,1243],{"__ignoreMap":39},[43,904,905],{"class":45,"line":46},[43,906,50],{"class":49},[43,908,909],{"class":45,"line":53},[43,910,911],{"class":49},"\u002F\u002F │ init() execution order (guaranteed by the runtime):                │\n",[43,913,914],{"class":45,"line":59},[43,915,916],{"class":49},"\u002F\u002F │   1. All imported packages' init()s run first (depth-first)        │\n",[43,918,919],{"class":45,"line":65},[43,920,921],{"class":49},"\u002F\u002F │   2. Package-level var initializers run (in declaration order)     │\n",[43,923,924],{"class":45,"line":71},[43,925,926],{"class":49},"\u002F\u002F │   3. All init() functions in THIS package run (in file order,      │\n",[43,928,929],{"class":45,"line":77},[43,930,931],{"class":49},"\u002F\u002F │      then declaration order within a file)                         │\n",[43,933,934],{"class":45,"line":83},[43,935,936],{"class":49},"\u002F\u002F │   4. main() runs                                                   │\n",[43,938,939],{"class":45,"line":89},[43,940,941],{"class":49},"\u002F\u002F │                                                                    │\n",[43,943,944],{"class":45,"line":95},[43,945,946],{"class":49},"\u002F\u002F │ ⚠️ Cross-file init() order = alphabetical by filename (not         │\n",[43,948,949],{"class":45,"line":101},[43,950,951],{"class":49},"\u002F\u002F │    guaranteed by spec, but this is what the toolchain does).       │\n",[43,953,954],{"class":45,"line":107},[43,955,956],{"class":49},"\u002F\u002F │    NEVER rely on cross-file init() order — merge into one init()   │\n",[43,958,959],{"class":45,"line":113},[43,960,961],{"class":49},"\u002F\u002F │    if order matters.                                               │\n",[43,963,964],{"class":45,"line":119},[43,965,98],{"class":49},[43,967,968],{"class":45,"line":125},[43,969,226],{"emptyLinePlaceholder":225},[43,971,972,974],{"class":45,"line":131},[43,973,391],{"class":188},[43,975,976],{"class":175}," database\n",[43,978,979],{"class":45,"line":137},[43,980,226],{"emptyLinePlaceholder":225},[43,982,983,985],{"class":45,"line":142},[43,984,635],{"class":188},[43,986,797],{"class":409},[43,988,989,992,994,997],{"class":45,"line":148},[43,990,991],{"class":409},"    pool    ",[43,993,568],{"class":188},[43,995,996],{"class":175},"ConnectionPool",[43,998,999],{"class":49},"    \u002F\u002F initialized in init()\n",[43,1001,1002,1005],{"class":45,"line":323},[43,1003,1004],{"class":409},"    driver  ",[43,1006,499],{"class":188},[43,1008,1009],{"class":45,"line":329},[43,1010,460],{"class":409},[43,1012,1013],{"class":45,"line":335},[43,1014,226],{"emptyLinePlaceholder":225},[43,1016,1017,1019,1022],{"class":45,"line":341},[43,1018,518],{"class":188},[43,1020,1021],{"class":175}," init",[43,1023,1024],{"class":409},"() {\n",[43,1026,1027],{"class":45,"line":347},[43,1028,1029],{"class":49},"    \u002F\u002F Runs ONCE per process, after package vars, before main.\n",[43,1031,1032],{"class":45,"line":353},[43,1033,1034],{"class":49},"    \u002F\u002F Multiple init()s per file are allowed (run in order).\n",[43,1036,1037,1040,1042,1045,1047,1050],{"class":45,"line":603},[43,1038,1039],{"class":409},"    pool ",[43,1041,641],{"class":188},[43,1043,1044],{"class":175}," NewConnectionPool",[43,1046,524],{"class":409},[43,1048,1049],{"class":213},"10",[43,1051,460],{"class":409},[43,1053,1054,1057,1059],{"class":45,"line":608},[43,1055,1056],{"class":409},"    driver ",[43,1058,641],{"class":188},[43,1060,1061],{"class":178}," \"postgres\"\n",[43,1063,1064],{"class":45,"line":613},[43,1065,504],{"class":409},[43,1067,1068],{"class":45,"line":619},[43,1069,226],{"emptyLinePlaceholder":225},[43,1071,1072,1074,1076],{"class":45,"line":627},[43,1073,518],{"class":188},[43,1075,1021],{"class":175},[43,1077,1024],{"class":409},[43,1079,1080],{"class":45,"line":632},[43,1081,1082],{"class":49},"    \u002F\u002F Second init() in same file — runs after the one above.\n",[43,1084,1085,1088,1091,1094,1097],{"class":45,"line":661},[43,1086,1087],{"class":188},"    if",[43,1089,1090],{"class":409}," pool ",[43,1092,1093],{"class":188},"==",[43,1095,1096],{"class":213}," nil",[43,1098,483],{"class":409},[43,1100,1101,1104,1106,1109,1112],{"class":45,"line":666},[43,1102,1103],{"class":175},"        panic",[43,1105,524],{"class":409},[43,1107,1108],{"class":178},"\"database: pool not initialized\"",[43,1110,1111],{"class":409},")  ",[43,1113,1114],{"class":49},"\u002F\u002F fail fast at startup\n",[43,1116,1117],{"class":45,"line":694},[43,1118,1119],{"class":409},"    }\n",[43,1121,1122],{"class":45,"line":708},[43,1123,504],{"class":409},[43,1125,1127],{"class":45,"line":1126},35,[43,1128,226],{"emptyLinePlaceholder":225},[43,1130,1132],{"class":45,"line":1131},36,[43,1133,1134],{"class":49},"\u002F\u002F ❌ ANTI-PATTERN: init() doing I\u002FO (file reads, network calls)\n",[43,1136,1138],{"class":45,"line":1137},37,[43,1139,1140],{"class":49},"\u002F\u002F func init() {\n",[43,1142,1144,1147],{"class":45,"line":1143},38,[43,1145,1146],{"class":49},"\u002F\u002F     data, _ := os.ReadFile(\"config.yaml\")",[43,1148,1149],{"class":49},"  \u002F\u002F no error handling, no context\n",[43,1151,1153],{"class":45,"line":1152},39,[43,1154,1155],{"class":49},"\u002F\u002F     config = parseYaml(data)\n",[43,1157,1159],{"class":45,"line":1158},40,[43,1160,1161],{"class":49},"\u002F\u002F }\n",[43,1163,1165],{"class":45,"line":1164},41,[43,1166,1167],{"class":49},"\u002F\u002F Problems: untestable, no error propagation, blocks startup, no way to\n",[43,1169,1171],{"class":45,"line":1170},42,[43,1172,1173],{"class":49},"\u002F\u002F pass a different config in tests.\n",[43,1175,1177],{"class":45,"line":1176},43,[43,1178,226],{"emptyLinePlaceholder":225},[43,1180,1182],{"class":45,"line":1181},44,[43,1183,1184],{"class":49},"\u002F\u002F ✅ CORRECT: explicit initialization function called from main()\n",[43,1186,1188,1190,1193,1195,1198,1201,1203,1205],{"class":45,"line":1187},45,[43,1189,518],{"class":188},[43,1191,1192],{"class":175}," Init",[43,1194,524],{"class":409},[43,1196,1197],{"class":527},"cfg",[43,1199,1200],{"class":175}," Config",[43,1202,682],{"class":409},[43,1204,576],{"class":188},[43,1206,483],{"class":409},[43,1208,1210,1213,1216],{"class":45,"line":1209},46,[43,1211,1212],{"class":188},"    var",[43,1214,1215],{"class":409}," err ",[43,1217,1218],{"class":188},"error\n",[43,1220,1222,1225,1227,1229],{"class":45,"line":1221},47,[43,1223,1224],{"class":409},"    pool, err ",[43,1226,641],{"class":188},[43,1228,1044],{"class":175},[43,1230,1231],{"class":409},"(cfg.PoolSize)\n",[43,1233,1235,1237,1240],{"class":45,"line":1234},48,[43,1236,589],{"class":188},[43,1238,1239],{"class":409}," err  ",[43,1241,1242],{"class":49},"\u002F\u002F caller handles the error\n",[43,1244,1246],{"class":45,"line":1245},49,[43,1247,504],{"class":409},[27,1249,1251,1252,1254],{"id":1250},"the-go-command-production-subcommands","The ",[18,1253,24],{}," Command — Production Subcommands",[32,1256,1257],{"language":159},[35,1258,1260],{"className":162,"code":1259,"language":159,"meta":39,"style":39},"# === BUILD ===\ngo build -o bin\u002Fmyapp .\u002Fcmd\u002Fmyapp              # build specific binary\ngo build .\u002F...                                   # compile-check all packages (no binary)\ngo build -x .\u002F...                                # print all compile\u002Flink commands (debug)\ngo build -work .\u002F...                             # keep temp build dir (inspect intermediate)\n\n# === TEST ===\ngo test .\u002F...                                    # all packages\ngo test -run 'TestUser' .\u002Finternal\u002Fuser\u002F         # regex filter\ngo test -count=1 .\u002F...                           # disable test result caching\ngo test -shuffle=on .\u002F...                        # randomize test order (Go 1.17+)\ngo test -parallel=4 .\u002F...                        # max parallel test packages\ngo test -timeout=30s .\u002F...                       # fail if a package exceeds 30s\ngo test -fuzz=FuzzParse -fuzztime=1m .\u002F...       # fuzz for 1 minute (Go 1.18+)\ngo test -coverprofile=c.out -coverpkg=.\u002F... .\u002F...  # cross-package coverage\n\n# === FORMAT & LINT ===\ngofmt -w -s .                                    # -s = simplify (remove redundant ops)\ngoimports -w -local example.com\u002Fmyapp .          # group local imports separately\n\n# === MODULE ===\ngo mod tidy -compat=1.22                         # avoid adding go 1.23 to go.mod\ngo mod download                                  # pre-fetch deps (CI cache step)\ngo mod verify                                    # verify go.sum hashes match cache\ngo mod why -m github.com\u002Flib\u002Fpq                  # trace why a dep is needed\ngo mod graph                                     # full dependency DAG\ngo mod edit -go=1.22                             # change go directive (scripting)\n\n# === DOC ===\ngo doc -all fmt                                  # all exports including unexported\ngo doc -src fmt.Println                          # show source of the function\ngo doc -u fmt.printf                             # include unexported methods\n",[18,1261,1262,1267,1285,1297,1311,1325,1329,1334,1346,1364,1378,1392,1406,1420,1437,1454,1458,1463,1479,1497,1501,1506,1522,1534,1546,1563,1575,1590,1594,1599,1615,1630],{"__ignoreMap":39},[43,1263,1264],{"class":45,"line":46},[43,1265,1266],{"class":49},"# === BUILD ===\n",[43,1268,1269,1271,1274,1277,1279,1282],{"class":45,"line":53},[43,1270,24],{"class":175},[43,1272,1273],{"class":178}," build",[43,1275,1276],{"class":213}," -o",[43,1278,185],{"class":178},[43,1280,1281],{"class":178}," .\u002Fcmd\u002Fmyapp",[43,1283,1284],{"class":49},"              # build specific binary\n",[43,1286,1287,1289,1291,1294],{"class":45,"line":59},[43,1288,24],{"class":175},[43,1290,1273],{"class":178},[43,1292,1293],{"class":178}," .\u002F...",[43,1295,1296],{"class":49},"                                   # compile-check all packages (no binary)\n",[43,1298,1299,1301,1303,1306,1308],{"class":45,"line":65},[43,1300,24],{"class":175},[43,1302,1273],{"class":178},[43,1304,1305],{"class":213}," -x",[43,1307,1293],{"class":178},[43,1309,1310],{"class":49},"                                # print all compile\u002Flink commands (debug)\n",[43,1312,1313,1315,1317,1320,1322],{"class":45,"line":71},[43,1314,24],{"class":175},[43,1316,1273],{"class":178},[43,1318,1319],{"class":213}," -work",[43,1321,1293],{"class":178},[43,1323,1324],{"class":49},"                             # keep temp build dir (inspect intermediate)\n",[43,1326,1327],{"class":45,"line":77},[43,1328,226],{"emptyLinePlaceholder":225},[43,1330,1331],{"class":45,"line":83},[43,1332,1333],{"class":49},"# === TEST ===\n",[43,1335,1336,1338,1341,1343],{"class":45,"line":89},[43,1337,24],{"class":175},[43,1339,1340],{"class":178}," test",[43,1342,1293],{"class":178},[43,1344,1345],{"class":49},"                                    # all packages\n",[43,1347,1348,1350,1352,1355,1358,1361],{"class":45,"line":95},[43,1349,24],{"class":175},[43,1351,1340],{"class":178},[43,1353,1354],{"class":213}," -run",[43,1356,1357],{"class":178}," 'TestUser'",[43,1359,1360],{"class":178}," .\u002Finternal\u002Fuser\u002F",[43,1362,1363],{"class":49},"         # regex filter\n",[43,1365,1366,1368,1370,1373,1375],{"class":45,"line":101},[43,1367,24],{"class":175},[43,1369,1340],{"class":178},[43,1371,1372],{"class":213}," -count=1",[43,1374,1293],{"class":178},[43,1376,1377],{"class":49},"                           # disable test result caching\n",[43,1379,1380,1382,1384,1387,1389],{"class":45,"line":107},[43,1381,24],{"class":175},[43,1383,1340],{"class":178},[43,1385,1386],{"class":213}," -shuffle=on",[43,1388,1293],{"class":178},[43,1390,1391],{"class":49},"                        # randomize test order (Go 1.17+)\n",[43,1393,1394,1396,1398,1401,1403],{"class":45,"line":113},[43,1395,24],{"class":175},[43,1397,1340],{"class":178},[43,1399,1400],{"class":213}," -parallel=4",[43,1402,1293],{"class":178},[43,1404,1405],{"class":49},"                        # max parallel test packages\n",[43,1407,1408,1410,1412,1415,1417],{"class":45,"line":119},[43,1409,24],{"class":175},[43,1411,1340],{"class":178},[43,1413,1414],{"class":213}," -timeout=30s",[43,1416,1293],{"class":178},[43,1418,1419],{"class":49},"                       # fail if a package exceeds 30s\n",[43,1421,1422,1424,1426,1429,1432,1434],{"class":45,"line":125},[43,1423,24],{"class":175},[43,1425,1340],{"class":178},[43,1427,1428],{"class":213}," -fuzz=FuzzParse",[43,1430,1431],{"class":213}," -fuzztime=1m",[43,1433,1293],{"class":178},[43,1435,1436],{"class":49},"       # fuzz for 1 minute (Go 1.18+)\n",[43,1438,1439,1441,1443,1446,1449,1451],{"class":45,"line":131},[43,1440,24],{"class":175},[43,1442,1340],{"class":178},[43,1444,1445],{"class":213}," -coverprofile=c.out",[43,1447,1448],{"class":213}," -coverpkg=.\u002F...",[43,1450,1293],{"class":178},[43,1452,1453],{"class":49},"  # cross-package coverage\n",[43,1455,1456],{"class":45,"line":137},[43,1457,226],{"emptyLinePlaceholder":225},[43,1459,1460],{"class":45,"line":142},[43,1461,1462],{"class":49},"# === FORMAT & LINT ===\n",[43,1464,1465,1468,1471,1473,1476],{"class":45,"line":148},[43,1466,1467],{"class":175},"gofmt",[43,1469,1470],{"class":213}," -w",[43,1472,243],{"class":213},[43,1474,1475],{"class":178}," .",[43,1477,1478],{"class":49},"                                    # -s = simplify (remove redundant ops)\n",[43,1480,1481,1484,1486,1489,1492,1494],{"class":45,"line":323},[43,1482,1483],{"class":175},"goimports",[43,1485,1470],{"class":213},[43,1487,1488],{"class":213}," -local",[43,1490,1491],{"class":178}," example.com\u002Fmyapp",[43,1493,1475],{"class":178},[43,1495,1496],{"class":49},"          # group local imports separately\n",[43,1498,1499],{"class":45,"line":329},[43,1500,226],{"emptyLinePlaceholder":225},[43,1502,1503],{"class":45,"line":335},[43,1504,1505],{"class":49},"# === MODULE ===\n",[43,1507,1508,1510,1513,1516,1519],{"class":45,"line":341},[43,1509,24],{"class":175},[43,1511,1512],{"class":178}," mod",[43,1514,1515],{"class":178}," tidy",[43,1517,1518],{"class":213}," -compat=1.22",[43,1520,1521],{"class":49},"                         # avoid adding go 1.23 to go.mod\n",[43,1523,1524,1526,1528,1531],{"class":45,"line":347},[43,1525,24],{"class":175},[43,1527,1512],{"class":178},[43,1529,1530],{"class":178}," download",[43,1532,1533],{"class":49},"                                  # pre-fetch deps (CI cache step)\n",[43,1535,1536,1538,1540,1543],{"class":45,"line":353},[43,1537,24],{"class":175},[43,1539,1512],{"class":178},[43,1541,1542],{"class":178}," verify",[43,1544,1545],{"class":49},"                                    # verify go.sum hashes match cache\n",[43,1547,1548,1550,1552,1555,1557,1560],{"class":45,"line":603},[43,1549,24],{"class":175},[43,1551,1512],{"class":178},[43,1553,1554],{"class":178}," why",[43,1556,313],{"class":213},[43,1558,1559],{"class":178}," github.com\u002Flib\u002Fpq",[43,1561,1562],{"class":49},"                  # trace why a dep is needed\n",[43,1564,1565,1567,1569,1572],{"class":45,"line":608},[43,1566,24],{"class":175},[43,1568,1512],{"class":178},[43,1570,1571],{"class":178}," graph",[43,1573,1574],{"class":49},"                                     # full dependency DAG\n",[43,1576,1577,1579,1581,1584,1587],{"class":45,"line":613},[43,1578,24],{"class":175},[43,1580,1512],{"class":178},[43,1582,1583],{"class":178}," edit",[43,1585,1586],{"class":213}," -go=1.22",[43,1588,1589],{"class":49},"                             # change go directive (scripting)\n",[43,1591,1592],{"class":45,"line":619},[43,1593,226],{"emptyLinePlaceholder":225},[43,1595,1596],{"class":45,"line":627},[43,1597,1598],{"class":49},"# === DOC ===\n",[43,1600,1601,1603,1606,1609,1612],{"class":45,"line":632},[43,1602,24],{"class":175},[43,1604,1605],{"class":178}," doc",[43,1607,1608],{"class":213}," -all",[43,1610,1611],{"class":178}," fmt",[43,1613,1614],{"class":49},"                                  # all exports including unexported\n",[43,1616,1617,1619,1621,1624,1627],{"class":45,"line":661},[43,1618,24],{"class":175},[43,1620,1605],{"class":178},[43,1622,1623],{"class":213}," -src",[43,1625,1626],{"class":178}," fmt.Println",[43,1628,1629],{"class":49},"                          # show source of the function\n",[43,1631,1632,1634,1636,1639,1642],{"class":45,"line":666},[43,1633,24],{"class":175},[43,1635,1605],{"class":178},[43,1637,1638],{"class":213}," -u",[43,1640,1641],{"class":178}," fmt.printf",[43,1643,1644],{"class":49},"                             # include unexported methods\n",[153,1646,1648],{"id":1647},"the-test-cache-when-tests-dont-re-run","The test cache — when tests don't re-run",[32,1650,1651],{"language":159},[35,1652,1654],{"className":162,"code":1653,"language":159,"meta":39,"style":39},"# Go caches test results keyed on: package + source files + build flags + env.\n# If nothing changed, `go test` prints \"ok  example.com\u002Fmyapp\u002Fpkg  (cached)\"\n# and doesn't re-run. This is fast but can hide flaky tests.\n\n# Force re-run (ignore cache):\ngo test -count=1 .\u002F...\n\n# The cache is invalidated by:\n#   - Any source file change in the package\n#   - -race, -tags, -trimpath flag changes\n#   - GOOS\u002FGOARCH changes\n#   - Env vars listed in GODEBUG (and some others)\n\n# Cache lives in $GOCACHE:\ngo env GOCACHE    # \u002FUsers\u002Fyou\u002FLibrary\u002FCaches\u002Fgo-build\ngo clean -testcache   # clear only test results\ngo clean -cache       # clear entire build cache (recompile everything next run)\n",[18,1655,1656,1661,1666,1671,1675,1680,1691,1695,1700,1705,1710,1715,1720,1724,1729,1742,1755],{"__ignoreMap":39},[43,1657,1658],{"class":45,"line":46},[43,1659,1660],{"class":49},"# Go caches test results keyed on: package + source files + build flags + env.\n",[43,1662,1663],{"class":45,"line":53},[43,1664,1665],{"class":49},"# If nothing changed, `go test` prints \"ok  example.com\u002Fmyapp\u002Fpkg  (cached)\"\n",[43,1667,1668],{"class":45,"line":59},[43,1669,1670],{"class":49},"# and doesn't re-run. This is fast but can hide flaky tests.\n",[43,1672,1673],{"class":45,"line":65},[43,1674,226],{"emptyLinePlaceholder":225},[43,1676,1677],{"class":45,"line":71},[43,1678,1679],{"class":49},"# Force re-run (ignore cache):\n",[43,1681,1682,1684,1686,1688],{"class":45,"line":77},[43,1683,24],{"class":175},[43,1685,1340],{"class":178},[43,1687,1372],{"class":213},[43,1689,1690],{"class":178}," .\u002F...\n",[43,1692,1693],{"class":45,"line":83},[43,1694,226],{"emptyLinePlaceholder":225},[43,1696,1697],{"class":45,"line":89},[43,1698,1699],{"class":49},"# The cache is invalidated by:\n",[43,1701,1702],{"class":45,"line":95},[43,1703,1704],{"class":49},"#   - Any source file change in the package\n",[43,1706,1707],{"class":45,"line":101},[43,1708,1709],{"class":49},"#   - -race, -tags, -trimpath flag changes\n",[43,1711,1712],{"class":45,"line":107},[43,1713,1714],{"class":49},"#   - GOOS\u002FGOARCH changes\n",[43,1716,1717],{"class":45,"line":113},[43,1718,1719],{"class":49},"#   - Env vars listed in GODEBUG (and some others)\n",[43,1721,1722],{"class":45,"line":119},[43,1723,226],{"emptyLinePlaceholder":225},[43,1725,1726],{"class":45,"line":125},[43,1727,1728],{"class":49},"# Cache lives in $GOCACHE:\n",[43,1730,1731,1733,1736,1739],{"class":45,"line":131},[43,1732,24],{"class":175},[43,1734,1735],{"class":178}," env",[43,1737,1738],{"class":178}," GOCACHE",[43,1740,1741],{"class":49},"    # \u002FUsers\u002Fyou\u002FLibrary\u002FCaches\u002Fgo-build\n",[43,1743,1744,1746,1749,1752],{"class":45,"line":137},[43,1745,24],{"class":175},[43,1747,1748],{"class":178}," clean",[43,1750,1751],{"class":213}," -testcache",[43,1753,1754],{"class":49},"   # clear only test results\n",[43,1756,1757,1759,1761,1764],{"class":45,"line":142},[43,1758,24],{"class":175},[43,1760,1748],{"class":178},[43,1762,1763],{"class":213}," -cache",[43,1765,1766],{"class":49},"       # clear entire build cache (recompile everything next run)\n",[27,1768,1770],{"id":1769},"file-naming-conventions-implicit-build-constraints","File Naming Conventions (Implicit Build Constraints)",[32,1772,1773],{"language":24},[35,1774,1776],{"className":37,"code":1775,"language":24,"meta":39,"style":39},"\u002F\u002F The Go toolchain applies implicit build constraints based on filename:\n\u002F\u002F\n\u002F\u002F   foo_linux.go       → only compiled on GOOS=linux\n\u002F\u002F   foo_darwin.go      → only compiled on GOOS=darwin\n\u002F\u002F   foo_amd64.go       → only compiled on GOARCH=amd64\n\u002F\u002F   foo_linux_arm64.go → only on linux\u002Farm64\n\u002F\u002F   foo_test.go        → only compiled by `go test` (not in production binary)\n\u002F\u002F   foo_unix.go        → only on Unix-like (linux, darwin, etc.) — uses \u002F\u002Fgo:build unix\n\u002F\u002F\n\u002F\u002F This is a NAMING convention — you don't need a \u002F\u002Fgo:build tag if the\n\u002F\u002F filename already encodes the constraint. But explicit tags are clearer\n\u002F\u002F for custom tags (production, debug, fastjson).\n\n\u002F\u002F File: crypto_linux.go    ← implicit: only on linux\npackage crypto\n\n\u002F\u002F File: crypto_other.go    ← everything else (needs \u002F\u002Fgo:build !linux)\n\u002F\u002Fgo:build !linux\npackage crypto\n",[18,1777,1778,1783,1787,1792,1797,1802,1807,1812,1820,1824,1832,1837,1842,1846,1851,1858,1862,1870,1875],{"__ignoreMap":39},[43,1779,1780],{"class":45,"line":46},[43,1781,1782],{"class":49},"\u002F\u002F The Go toolchain applies implicit build constraints based on filename:\n",[43,1784,1785],{"class":45,"line":53},[43,1786,104],{"class":49},[43,1788,1789],{"class":45,"line":59},[43,1790,1791],{"class":49},"\u002F\u002F   foo_linux.go       → only compiled on GOOS=linux\n",[43,1793,1794],{"class":45,"line":65},[43,1795,1796],{"class":49},"\u002F\u002F   foo_darwin.go      → only compiled on GOOS=darwin\n",[43,1798,1799],{"class":45,"line":71},[43,1800,1801],{"class":49},"\u002F\u002F   foo_amd64.go       → only compiled on GOARCH=amd64\n",[43,1803,1804],{"class":45,"line":77},[43,1805,1806],{"class":49},"\u002F\u002F   foo_linux_arm64.go → only on linux\u002Farm64\n",[43,1808,1809],{"class":45,"line":83},[43,1810,1811],{"class":49},"\u002F\u002F   foo_test.go        → only compiled by `go test` (not in production binary)\n",[43,1813,1814,1817],{"class":45,"line":89},[43,1815,1816],{"class":49},"\u002F\u002F   foo_unix.go        → only on Unix-like (linux, darwin, etc.) — uses",[43,1818,1819],{"class":49}," \u002F\u002Fgo:build unix\n",[43,1821,1822],{"class":45,"line":95},[43,1823,104],{"class":49},[43,1825,1826,1829],{"class":45,"line":101},[43,1827,1828],{"class":49},"\u002F\u002F This is a NAMING convention — you don't need a",[43,1830,1831],{"class":49}," \u002F\u002Fgo:build tag if the\n",[43,1833,1834],{"class":45,"line":107},[43,1835,1836],{"class":49},"\u002F\u002F filename already encodes the constraint. But explicit tags are clearer\n",[43,1838,1839],{"class":45,"line":113},[43,1840,1841],{"class":49},"\u002F\u002F for custom tags (production, debug, fastjson).\n",[43,1843,1844],{"class":45,"line":119},[43,1845,226],{"emptyLinePlaceholder":225},[43,1847,1848],{"class":45,"line":125},[43,1849,1850],{"class":49},"\u002F\u002F File: crypto_linux.go    ← implicit: only on linux\n",[43,1852,1853,1855],{"class":45,"line":131},[43,1854,391],{"class":188},[43,1856,1857],{"class":175}," crypto\n",[43,1859,1860],{"class":45,"line":137},[43,1861,226],{"emptyLinePlaceholder":225},[43,1863,1864,1867],{"class":45,"line":142},[43,1865,1866],{"class":49},"\u002F\u002F File: crypto_other.go    ← everything else (needs",[43,1868,1869],{"class":49}," \u002F\u002Fgo:build !linux)\n",[43,1871,1872],{"class":45,"line":148},[43,1873,1874],{"class":49},"\u002F\u002Fgo:build !linux\n",[43,1876,1877,1879],{"class":45,"line":323},[43,1878,391],{"class":188},[43,1880,1857],{"class":175},[27,1882,1884,1887,1888,1887,1891],{"id":1883},"osargs-vs-flag-vs-cobra",[18,1885,1886],{},"os.Args"," vs ",[18,1889,1890],{},"flag",[18,1892,1893],{},"cobra",[32,1895,1896],{"language":24},[35,1897,1899],{"className":37,"code":1898,"language":24,"meta":39,"style":39},"\u002F\u002F os.Args — raw access, no parsing. Fine for single-positional-arg tools.\npackage main\n\nimport (\n    \"fmt\"\n    \"os\"\n)\n\nfunc main() {\n    if len(os.Args) != 2 {\n        fmt.Fprintf(os.Stderr, \"usage: %s \u003Cinput>\\n\", os.Args[0])\n        os.Exit(2)  \u002F\u002F 2 = usage error (convention), 1 = runtime error\n    }\n    input := os.Args[1]\n    _ = input\n}\n",[18,1900,1901,1906,1913,1917,1923,1932,1941,1945,1949,1958,1975,2009,2027,2031,2048,2057],{"__ignoreMap":39},[43,1902,1903],{"class":45,"line":46},[43,1904,1905],{"class":49},"\u002F\u002F os.Args — raw access, no parsing. Fine for single-positional-arg tools.\n",[43,1907,1908,1910],{"class":45,"line":53},[43,1909,391],{"class":188},[43,1911,1912],{"class":175}," main\n",[43,1914,1915],{"class":45,"line":59},[43,1916,226],{"emptyLinePlaceholder":225},[43,1918,1919,1921],{"class":45,"line":65},[43,1920,406],{"class":188},[43,1922,797],{"class":409},[43,1924,1925,1927,1930],{"class":45,"line":71},[43,1926,418],{"class":178},[43,1928,1929],{"class":175},"fmt",[43,1931,424],{"class":178},[43,1933,1934,1936,1939],{"class":45,"line":77},[43,1935,418],{"class":178},[43,1937,1938],{"class":175},"os",[43,1940,424],{"class":178},[43,1942,1943],{"class":45,"line":83},[43,1944,460],{"class":409},[43,1946,1947],{"class":45,"line":89},[43,1948,226],{"emptyLinePlaceholder":225},[43,1950,1951,1953,1956],{"class":45,"line":95},[43,1952,518],{"class":188},[43,1954,1955],{"class":175}," main",[43,1957,1024],{"class":409},[43,1959,1960,1962,1965,1968,1970,1973],{"class":45,"line":101},[43,1961,1087],{"class":188},[43,1963,1964],{"class":175}," len",[43,1966,1967],{"class":409},"(os.Args) ",[43,1969,702],{"class":188},[43,1971,1972],{"class":213}," 2",[43,1974,483],{"class":409},[43,1976,1977,1980,1983,1986,1989,1992,1995,1998,2000,2003,2006],{"class":45,"line":107},[43,1978,1979],{"class":409},"        fmt.",[43,1981,1982],{"class":175},"Fprintf",[43,1984,1985],{"class":409},"(os.Stderr, ",[43,1987,1988],{"class":178},"\"usage: ",[43,1990,1991],{"class":213},"%s",[43,1993,1994],{"class":178}," \u003Cinput>",[43,1996,1997],{"class":213},"\\n",[43,1999,810],{"class":178},[43,2001,2002],{"class":409},", os.Args[",[43,2004,2005],{"class":213},"0",[43,2007,2008],{"class":409},"])\n",[43,2010,2011,2014,2017,2019,2022,2024],{"class":45,"line":113},[43,2012,2013],{"class":409},"        os.",[43,2015,2016],{"class":175},"Exit",[43,2018,524],{"class":409},[43,2020,2021],{"class":213},"2",[43,2023,1111],{"class":409},[43,2025,2026],{"class":49},"\u002F\u002F 2 = usage error (convention), 1 = runtime error\n",[43,2028,2029],{"class":45,"line":119},[43,2030,1119],{"class":409},[43,2032,2033,2036,2039,2042,2045],{"class":45,"line":125},[43,2034,2035],{"class":409},"    input ",[43,2037,2038],{"class":188},":=",[43,2040,2041],{"class":409}," os.Args[",[43,2043,2044],{"class":213},"1",[43,2046,2047],{"class":409},"]\n",[43,2049,2050,2052,2054],{"class":45,"line":131},[43,2051,823],{"class":409},[43,2053,641],{"class":188},[43,2055,2056],{"class":409}," input\n",[43,2058,2059],{"class":45,"line":137},[43,2060,504],{"class":409},[32,2062,2063],{"language":24},[35,2064,2066],{"className":37,"code":2065,"language":24,"meta":39,"style":39},"\u002F\u002F flag — stdlib flag parser. Good for simple CLIs.\npackage main\n\nimport (\n    \"flag\"\n    \"fmt\"\n    \"os\"\n)\n\nfunc main() {\n    \u002F\u002F Define flags BEFORE parsing. Defaults are used if flag is absent.\n    port := flag.Int(\"port\", 8080, \"port to listen on\")\n    host := flag.String(\"host\", \"0.0.0.0\", \"bind address\")\n    debug := flag.Bool(\"debug\", false, \"enable debug logging\")\n    flag.Parse()  \u002F\u002F parses os.Args[1:] — flags must come before positional args\n\n    \u002F\u002F flag.Args() = positional args (after flags)\n    args := flag.Args()\n    if len(args) > 0 {\n        fmt.Println(\"positional:\", args)\n    }\n\n    fmt.Printf(\"server: %s:%d (debug=%v)\\n\", *host, *port, *debug)\n}\n",[18,2067,2068,2073,2079,2083,2089,2097,2105,2113,2117,2121,2129,2134,2164,2193,2222,2236,2240,2245,2260,2277,2292,2296,2300,2351],{"__ignoreMap":39},[43,2069,2070],{"class":45,"line":46},[43,2071,2072],{"class":49},"\u002F\u002F flag — stdlib flag parser. Good for simple CLIs.\n",[43,2074,2075,2077],{"class":45,"line":53},[43,2076,391],{"class":188},[43,2078,1912],{"class":175},[43,2080,2081],{"class":45,"line":59},[43,2082,226],{"emptyLinePlaceholder":225},[43,2084,2085,2087],{"class":45,"line":65},[43,2086,406],{"class":188},[43,2088,797],{"class":409},[43,2090,2091,2093,2095],{"class":45,"line":71},[43,2092,418],{"class":178},[43,2094,1890],{"class":175},[43,2096,424],{"class":178},[43,2098,2099,2101,2103],{"class":45,"line":77},[43,2100,418],{"class":178},[43,2102,1929],{"class":175},[43,2104,424],{"class":178},[43,2106,2107,2109,2111],{"class":45,"line":83},[43,2108,418],{"class":178},[43,2110,1938],{"class":175},[43,2112,424],{"class":178},[43,2114,2115],{"class":45,"line":89},[43,2116,460],{"class":409},[43,2118,2119],{"class":45,"line":95},[43,2120,226],{"emptyLinePlaceholder":225},[43,2122,2123,2125,2127],{"class":45,"line":101},[43,2124,518],{"class":188},[43,2126,1955],{"class":175},[43,2128,1024],{"class":409},[43,2130,2131],{"class":45,"line":107},[43,2132,2133],{"class":49},"    \u002F\u002F Define flags BEFORE parsing. Defaults are used if flag is absent.\n",[43,2135,2136,2139,2141,2144,2147,2149,2152,2154,2157,2159,2162],{"class":45,"line":113},[43,2137,2138],{"class":409},"    port ",[43,2140,2038],{"class":188},[43,2142,2143],{"class":409}," flag.",[43,2145,2146],{"class":175},"Int",[43,2148,524],{"class":409},[43,2150,2151],{"class":178},"\"port\"",[43,2153,540],{"class":409},[43,2155,2156],{"class":213},"8080",[43,2158,540],{"class":409},[43,2160,2161],{"class":178},"\"port to listen on\"",[43,2163,460],{"class":409},[43,2165,2166,2169,2171,2173,2176,2178,2181,2183,2186,2188,2191],{"class":45,"line":119},[43,2167,2168],{"class":409},"    host ",[43,2170,2038],{"class":188},[43,2172,2143],{"class":409},[43,2174,2175],{"class":175},"String",[43,2177,524],{"class":409},[43,2179,2180],{"class":178},"\"host\"",[43,2182,540],{"class":409},[43,2184,2185],{"class":178},"\"0.0.0.0\"",[43,2187,540],{"class":409},[43,2189,2190],{"class":178},"\"bind address\"",[43,2192,460],{"class":409},[43,2194,2195,2198,2200,2202,2205,2207,2210,2212,2215,2217,2220],{"class":45,"line":125},[43,2196,2197],{"class":409},"    debug ",[43,2199,2038],{"class":188},[43,2201,2143],{"class":409},[43,2203,2204],{"class":175},"Bool",[43,2206,524],{"class":409},[43,2208,2209],{"class":178},"\"debug\"",[43,2211,540],{"class":409},[43,2213,2214],{"class":213},"false",[43,2216,540],{"class":409},[43,2218,2219],{"class":178},"\"enable debug logging\"",[43,2221,460],{"class":409},[43,2223,2224,2227,2230,2233],{"class":45,"line":131},[43,2225,2226],{"class":409},"    flag.",[43,2228,2229],{"class":175},"Parse",[43,2231,2232],{"class":409},"()  ",[43,2234,2235],{"class":49},"\u002F\u002F parses os.Args[1:] — flags must come before positional args\n",[43,2237,2238],{"class":45,"line":137},[43,2239,226],{"emptyLinePlaceholder":225},[43,2241,2242],{"class":45,"line":142},[43,2243,2244],{"class":49},"    \u002F\u002F flag.Args() = positional args (after flags)\n",[43,2246,2247,2250,2252,2254,2257],{"class":45,"line":148},[43,2248,2249],{"class":409},"    args ",[43,2251,2038],{"class":188},[43,2253,2143],{"class":409},[43,2255,2256],{"class":175},"Args",[43,2258,2259],{"class":409},"()\n",[43,2261,2262,2264,2266,2269,2272,2275],{"class":45,"line":323},[43,2263,1087],{"class":188},[43,2265,1964],{"class":175},[43,2267,2268],{"class":409},"(args) ",[43,2270,2271],{"class":188},">",[43,2273,2274],{"class":213}," 0",[43,2276,483],{"class":409},[43,2278,2279,2281,2284,2286,2289],{"class":45,"line":329},[43,2280,1979],{"class":409},[43,2282,2283],{"class":175},"Println",[43,2285,524],{"class":409},[43,2287,2288],{"class":178},"\"positional:\"",[43,2290,2291],{"class":409},", args)\n",[43,2293,2294],{"class":45,"line":335},[43,2295,1119],{"class":409},[43,2297,2298],{"class":45,"line":341},[43,2299,226],{"emptyLinePlaceholder":225},[43,2301,2302,2305,2308,2310,2313,2315,2318,2321,2324,2327,2330,2332,2334,2336,2338,2341,2343,2346,2348],{"class":45,"line":347},[43,2303,2304],{"class":409},"    fmt.",[43,2306,2307],{"class":175},"Printf",[43,2309,524],{"class":409},[43,2311,2312],{"class":178},"\"server: ",[43,2314,1991],{"class":213},[43,2316,2317],{"class":178},":",[43,2319,2320],{"class":213},"%d",[43,2322,2323],{"class":178}," (debug=",[43,2325,2326],{"class":213},"%v",[43,2328,2329],{"class":178},")",[43,2331,1997],{"class":213},[43,2333,810],{"class":178},[43,2335,540],{"class":409},[43,2337,568],{"class":188},[43,2339,2340],{"class":409},"host, ",[43,2342,568],{"class":188},[43,2344,2345],{"class":409},"port, ",[43,2347,568],{"class":188},[43,2349,2350],{"class":409},"debug)\n",[43,2352,2353],{"class":45,"line":353},[43,2354,504],{"class":409},[32,2356,2357],{"language":159},[35,2358,2360],{"className":162,"code":2359,"language":159,"meta":39,"style":39},"# flag-style invocation:\n.\u002Fmyapp -port=9090 -debug file1.txt file2.txt\n#     port=9090, debug=true, args=[file1.txt file2.txt]\n\n.\u002Fmyapp --port 9090        # -- also works (flag accepts both - and --)\n.\u002Fmyapp -h                 # prints usage (flag generates -h\u002F-help automatically)\n\n# ⚠️ flag stops at the first non-flag arg:\n.\u002Fmyapp file.txt -port=9090   # port=8080 (default!) — -port is treated as positional\n",[18,2361,2362,2367,2384,2389,2393,2406,2416,2420,2425],{"__ignoreMap":39},[43,2363,2364],{"class":45,"line":46},[43,2365,2366],{"class":49},"# flag-style invocation:\n",[43,2368,2369,2372,2375,2378,2381],{"class":45,"line":53},[43,2370,2371],{"class":175},".\u002Fmyapp",[43,2373,2374],{"class":213}," -port=9090",[43,2376,2377],{"class":213}," -debug",[43,2379,2380],{"class":178}," file1.txt",[43,2382,2383],{"class":178}," file2.txt\n",[43,2385,2386],{"class":45,"line":59},[43,2387,2388],{"class":49},"#     port=9090, debug=true, args=[file1.txt file2.txt]\n",[43,2390,2391],{"class":45,"line":65},[43,2392,226],{"emptyLinePlaceholder":225},[43,2394,2395,2397,2400,2403],{"class":45,"line":71},[43,2396,2371],{"class":175},[43,2398,2399],{"class":213}," --port",[43,2401,2402],{"class":213}," 9090",[43,2404,2405],{"class":49},"        # -- also works (flag accepts both - and --)\n",[43,2407,2408,2410,2413],{"class":45,"line":77},[43,2409,2371],{"class":175},[43,2411,2412],{"class":213}," -h",[43,2414,2415],{"class":49},"                 # prints usage (flag generates -h\u002F-help automatically)\n",[43,2417,2418],{"class":45,"line":83},[43,2419,226],{"emptyLinePlaceholder":225},[43,2421,2422],{"class":45,"line":89},[43,2423,2424],{"class":49},"# ⚠️ flag stops at the first non-flag arg:\n",[43,2426,2427,2429,2432,2434],{"class":45,"line":95},[43,2428,2371],{"class":175},[43,2430,2431],{"class":178}," file.txt",[43,2433,2374],{"class":213},[43,2435,2436],{"class":49},"   # port=8080 (default!) — -port is treated as positional\n",[32,2438,2439],{"language":24},[35,2440,2442],{"className":37,"code":2441,"language":24,"meta":39,"style":39},"\u002F\u002F For production CLIs with subcommands (myapp user create, myapp user delete),\n\u002F\u002F use spf13\u002Fcobra or urfave\u002Fcli. The stdlib `flag` doesn't do subcommands.\n\u002F\u002F\n\u002F\u002F cobra example (pseudo):\n\u002F\u002F   rootCmd := &cobra.Command{Use: \"myapp\"}\n\u002F\u002F   userCmd := &cobra.Command{Use: \"user\"}\n\u002F\u002F   createCmd := &cobra.Command{\n\u002F\u002F       Use:   \"create\",\n\u002F\u002F       Args:  cobra.ExactArgs(1),\n\u002F\u002F       Run:   func(cmd *cobra.Command, args []string) { createUser(args[0]) },\n\u002F\u002F   }\n\u002F\u002F   userCmd.AddCommand(createCmd)\n\u002F\u002F   rootCmd.AddCommand(userCmd)\n\u002F\u002F   rootCmd.Execute()\n",[18,2443,2444,2449,2454,2458,2463,2468,2473,2478,2483,2488,2493,2498,2503,2508],{"__ignoreMap":39},[43,2445,2446],{"class":45,"line":46},[43,2447,2448],{"class":49},"\u002F\u002F For production CLIs with subcommands (myapp user create, myapp user delete),\n",[43,2450,2451],{"class":45,"line":53},[43,2452,2453],{"class":49},"\u002F\u002F use spf13\u002Fcobra or urfave\u002Fcli. The stdlib `flag` doesn't do subcommands.\n",[43,2455,2456],{"class":45,"line":59},[43,2457,104],{"class":49},[43,2459,2460],{"class":45,"line":65},[43,2461,2462],{"class":49},"\u002F\u002F cobra example (pseudo):\n",[43,2464,2465],{"class":45,"line":71},[43,2466,2467],{"class":49},"\u002F\u002F   rootCmd := &cobra.Command{Use: \"myapp\"}\n",[43,2469,2470],{"class":45,"line":77},[43,2471,2472],{"class":49},"\u002F\u002F   userCmd := &cobra.Command{Use: \"user\"}\n",[43,2474,2475],{"class":45,"line":83},[43,2476,2477],{"class":49},"\u002F\u002F   createCmd := &cobra.Command{\n",[43,2479,2480],{"class":45,"line":89},[43,2481,2482],{"class":49},"\u002F\u002F       Use:   \"create\",\n",[43,2484,2485],{"class":45,"line":95},[43,2486,2487],{"class":49},"\u002F\u002F       Args:  cobra.ExactArgs(1),\n",[43,2489,2490],{"class":45,"line":101},[43,2491,2492],{"class":49},"\u002F\u002F       Run:   func(cmd *cobra.Command, args []string) { createUser(args[0]) },\n",[43,2494,2495],{"class":45,"line":107},[43,2496,2497],{"class":49},"\u002F\u002F   }\n",[43,2499,2500],{"class":45,"line":113},[43,2501,2502],{"class":49},"\u002F\u002F   userCmd.AddCommand(createCmd)\n",[43,2504,2505],{"class":45,"line":119},[43,2506,2507],{"class":49},"\u002F\u002F   rootCmd.AddCommand(userCmd)\n",[43,2509,2510],{"class":45,"line":125},[43,2511,2512],{"class":49},"\u002F\u002F   rootCmd.Execute()\n",[27,2514,2516],{"id":2515},"exit-codes","Exit Codes",[32,2518,2519],{"language":24},[35,2520,2522],{"className":37,"code":2521,"language":24,"meta":39,"style":39},"package main\n\nimport \"os\"\n\n\u002F\u002F Exit code conventions (align with sysexits.h where possible):\n\u002F\u002F   0  — success\n\u002F\u002F   1  — general error (catch-all)\n\u002F\u002F   2  — usage error \u002F bad flags\n\u002F\u002F   64-78 — sysexits.h codes (EX_USAGE=64, EX_DATAERR=65, EX_NOINPUT=66, ...)\n\nfunc main() {\n    if err := run(); err != nil {\n        \u002F\u002F NEVER call os.Exit from a function that has deferred cleanup —\n        \u002F\u002F os.Exit skips all deferred functions! Instead, return the error\n        \u002F\u002F and call os.Exit only in main().\n        os.Exit(1)\n    }\n}\n\nfunc run() error {\n    \u002F\u002F deferred functions DO run when this returns an error\n    defer cleanup()\n    \u002F\u002F ...\n    return nil\n}\n\nfunc cleanup() {\n    \u002F\u002F This runs. If os.Exit(1) were called inside run(), this would NOT run.\n}\n",[18,2523,2524,2530,2534,2545,2549,2554,2559,2564,2569,2574,2578,2586,2606,2611,2616,2621,2633,2637,2641,2645,2658,2663,2673,2677,2684,2688,2692,2700,2705],{"__ignoreMap":39},[43,2525,2526,2528],{"class":45,"line":46},[43,2527,391],{"class":188},[43,2529,1912],{"class":175},[43,2531,2532],{"class":45,"line":53},[43,2533,226],{"emptyLinePlaceholder":225},[43,2535,2536,2538,2541,2543],{"class":45,"line":59},[43,2537,406],{"class":188},[43,2539,2540],{"class":178}," \"",[43,2542,1938],{"class":175},[43,2544,424],{"class":178},[43,2546,2547],{"class":45,"line":65},[43,2548,226],{"emptyLinePlaceholder":225},[43,2550,2551],{"class":45,"line":71},[43,2552,2553],{"class":49},"\u002F\u002F Exit code conventions (align with sysexits.h where possible):\n",[43,2555,2556],{"class":45,"line":77},[43,2557,2558],{"class":49},"\u002F\u002F   0  — success\n",[43,2560,2561],{"class":45,"line":83},[43,2562,2563],{"class":49},"\u002F\u002F   1  — general error (catch-all)\n",[43,2565,2566],{"class":45,"line":89},[43,2567,2568],{"class":49},"\u002F\u002F   2  — usage error \u002F bad flags\n",[43,2570,2571],{"class":45,"line":95},[43,2572,2573],{"class":49},"\u002F\u002F   64-78 — sysexits.h codes (EX_USAGE=64, EX_DATAERR=65, EX_NOINPUT=66, ...)\n",[43,2575,2576],{"class":45,"line":101},[43,2577,226],{"emptyLinePlaceholder":225},[43,2579,2580,2582,2584],{"class":45,"line":107},[43,2581,518],{"class":188},[43,2583,1955],{"class":175},[43,2585,1024],{"class":409},[43,2587,2588,2590,2592,2594,2597,2600,2602,2604],{"class":45,"line":113},[43,2589,1087],{"class":188},[43,2591,1215],{"class":409},[43,2593,2038],{"class":188},[43,2595,2596],{"class":175}," run",[43,2598,2599],{"class":409},"(); err ",[43,2601,702],{"class":188},[43,2603,1096],{"class":213},[43,2605,483],{"class":409},[43,2607,2608],{"class":45,"line":119},[43,2609,2610],{"class":49},"        \u002F\u002F NEVER call os.Exit from a function that has deferred cleanup —\n",[43,2612,2613],{"class":45,"line":125},[43,2614,2615],{"class":49},"        \u002F\u002F os.Exit skips all deferred functions! Instead, return the error\n",[43,2617,2618],{"class":45,"line":131},[43,2619,2620],{"class":49},"        \u002F\u002F and call os.Exit only in main().\n",[43,2622,2623,2625,2627,2629,2631],{"class":45,"line":137},[43,2624,2013],{"class":409},[43,2626,2016],{"class":175},[43,2628,524],{"class":409},[43,2630,2044],{"class":213},[43,2632,460],{"class":409},[43,2634,2635],{"class":45,"line":142},[43,2636,1119],{"class":409},[43,2638,2639],{"class":45,"line":148},[43,2640,504],{"class":409},[43,2642,2643],{"class":45,"line":323},[43,2644,226],{"emptyLinePlaceholder":225},[43,2646,2647,2649,2651,2654,2656],{"class":45,"line":329},[43,2648,518],{"class":188},[43,2650,2596],{"class":175},[43,2652,2653],{"class":409},"() ",[43,2655,576],{"class":188},[43,2657,483],{"class":409},[43,2659,2660],{"class":45,"line":335},[43,2661,2662],{"class":49},"    \u002F\u002F deferred functions DO run when this returns an error\n",[43,2664,2665,2668,2671],{"class":45,"line":341},[43,2666,2667],{"class":188},"    defer",[43,2669,2670],{"class":175}," cleanup",[43,2672,2259],{"class":409},[43,2674,2675],{"class":45,"line":347},[43,2676,584],{"class":49},[43,2678,2679,2681],{"class":45,"line":353},[43,2680,589],{"class":188},[43,2682,2683],{"class":213}," nil\n",[43,2685,2686],{"class":45,"line":603},[43,2687,504],{"class":409},[43,2689,2690],{"class":45,"line":608},[43,2691,226],{"emptyLinePlaceholder":225},[43,2693,2694,2696,2698],{"class":45,"line":613},[43,2695,518],{"class":188},[43,2697,2670],{"class":175},[43,2699,1024],{"class":409},[43,2701,2702],{"class":45,"line":619},[43,2703,2704],{"class":49},"    \u002F\u002F This runs. If os.Exit(1) were called inside run(), this would NOT run.\n",[43,2706,2707],{"class":45,"line":627},[43,2708,504],{"class":409},[27,2710,2712],{"id":2711},"tips-tricks","💡 Tips & Tricks",[2714,2715,2716,2732,2741,2758,2766,2789,2802],"ul",{},[2717,2718,2719,2723,2724,2727,2728,2731],"li",{},[2720,2721,2722],"strong",{},"Performance",": ",[18,2725,2726],{},"go build -p N"," controls parallelism (N packages compiled simultaneously). Default = GOMAXPROCS. On CI with limited cores, ",[18,2729,2730],{},"-p 1"," serializes to reduce memory pressure.",[2717,2733,2734,2723,2737,2740],{},[2720,2735,2736],{},"Idiom",[18,2738,2739],{},"go test -race -count=1 -shuffle=on .\u002F..."," in CI — race detection, no cache, randomized order catches order-dependent test bugs.",[2717,2742,2743,2723,2746,2749,2750,2753,2754,2757],{},[2720,2744,2745],{},"Debug",[18,2747,2748],{},"go build -gcflags='all=-N -l'"," disables optimizations and inlining for the entire build — required for debugging with Delve (",[18,2751,2752],{},"dlv","). Without ",[18,2755,2756],{},"-N -l",", the debugger shows incorrect line numbers due to inlining.",[2717,2759,2760,2723,2762,2765],{},[2720,2761,2745],{},[18,2763,2764],{},"go test -run 'TestX' -v -count=1"," always re-runs with verbose output — use when debugging a single flaky test.",[2717,2767,2768,2723,2770,2773,2774,2777,2778,540,2781,540,2783,540,2785,2788],{},[2720,2769,2736],{},[18,2771,2772],{},"go install tool@version"," (Go 1.16+) installs to ",[18,2775,2776],{},"$GOBIN"," without modifying your module — use for developer tools (",[18,2779,2780],{},"golangci-lint",[18,2782,1483],{},[18,2784,2752],{},[18,2786,2787],{},"mockery",").",[2717,2790,2791,2723,2794,2797,2798,2801],{},[2720,2792,2793],{},"Portability",[18,2795,2796],{},"go env -w GOFLAGS=-mod=readonly"," sets a persistent env var — prevents accidental go.mod modification during builds. Override per-command with ",[18,2799,2800],{},"-mod=mod"," when you intentionally want to add deps.",[2717,2803,2804,2723,2806,2809,2810,2813],{},[2720,2805,2745],{},[18,2807,2808],{},"go tool trace trace.out"," opens the execution tracer (requires ",[18,2811,2812],{},"runtime\u002Ftrace"," in your code) — shows goroutine scheduling, GC pauses, and syscall blocking in a visual timeline.",[27,2815,2817],{"id":2816},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2714,2819,2820,2835,2853,2880,2894,2912,2938,2957,2970,2993],{},[2717,2821,2822,2723,2825,2828,2829,2831,2832,2834],{},[2720,2823,2824],{},"Unused imports = compile error",[18,2826,2827],{},"import \"fmt\""," without using ",[18,2830,1929],{}," fails. ",[18,2833,1483],{}," fixes this automatically on save.",[2717,2836,2837,2723,2840,2843,2844,2847,2848,2852],{},[2720,2838,2839],{},"Unused local variables = compile error",[18,2841,2842],{},"x := 5"," without reading ",[18,2845,2846],{},"x"," fails. (Unused ",[2849,2850,2851],"em",{},"package-level"," variables are fine — they might be used by other files.)",[2717,2854,2855,2723,2863,2865,2866,2869,2870,2873,2874,2876,2877,2879],{},[2720,2856,2857,1887,2860],{},[18,2858,2859],{},"go run main.go",[18,2861,2862],{},"go run .",[18,2864,2859],{}," compiles only ",[18,2867,2868],{},"main.go"," — fails if ",[18,2871,2872],{},"main"," calls functions in other files. ",[18,2875,2862],{}," compiles the whole package. Always use ",[18,2878,2862],{}," for multi-file packages.",[2717,2881,2882,2887,2888,2890,2891,2893],{},[2720,2883,2884,2886],{},[18,2885,20],{}," order across files",": within a package, ",[18,2889,20],{}," functions run in alphabetical filename order (toolchain behavior, not spec). Don't rely on it — merge into one ",[18,2892,20],{}," if order matters.",[2717,2895,2896,2902,2903,2905,2906,2908,2909,2911],{},[2720,2897,2898,2901],{},[18,2899,2900],{},"os.Exit"," skips deferred functions",": calling ",[18,2904,2900],{}," inside any function skips all deferred calls in the call stack. Always return an error to ",[18,2907,2872],{}," and call ",[18,2910,2900],{}," there.",[2717,2913,2914,2723,2919,2922,2923,2926,2927,2930,2931,2934,2935,2937],{},[2720,2915,2916,2918],{},[18,2917,1890],{}," stops at first positional arg",[18,2920,2921],{},".\u002Fmyapp file.txt -port=9090"," → ",[18,2924,2925],{},"-port"," is treated as positional, not parsed. Reorder: ",[18,2928,2929],{},".\u002Fmyapp -port=9090 file.txt",". Or use ",[18,2932,2933],{},"pflag","\u002F",[18,2936,1893],{}," which intermix.",[2717,2939,2940,2723,2943,2945,2946,2949,2950,2934,2953,2956],{},[2720,2941,2942],{},"Capitalization = visibility",[18,2944,2283],{}," (capital) is exported; ",[18,2947,2948],{},"println"," (lowercase) is package-private. The only visibility mechanism — no ",[18,2951,2952],{},"public",[18,2954,2955],{},"private"," keywords.",[2717,2958,2959,2965,2966,2969],{},[2720,2960,2961,2962,2964],{},"Multiple ",[18,2963,2872],{}," files in one directory",": fine — they compile together. But you can't have two ",[18,2967,2968],{},"func main()"," in the same package (compile error).",[2717,2971,2972,2723,2978,2980,2981,2984,2985,2988,2989,2992],{},[2720,2973,2974,2977],{},[18,2975,2976],{},"go build"," output name",[18,2979,2976],{}," in ",[18,2982,2983],{},"myapp\u002F"," produces ",[18,2986,2987],{},"myapp"," (named after the directory, not the module). ",[18,2990,2991],{},"go build -o name"," overrides.",[2717,2994,2995,2723,2998,3001,3002,3004,3005,3008,3009,3011],{},[2720,2996,2997],{},"Test binary vs production binary",[18,2999,3000],{},"_test.go"," files are excluded from ",[18,3003,2976],{}," but included in ",[18,3006,3007],{},"go test",". Test-only helpers go in ",[18,3010,3000],{}," files (they won't bloat the production binary).",[27,3013,3015],{"id":3014},"quick-quiz","🧠 Quick Quiz",[32,3017,3018],{"language":24},[35,3019,3021],{"className":37,"code":3020,"language":24,"meta":39,"style":39},"package main\n\nimport \"fmt\"\n\nfunc main() {\n    defer fmt.Println(\"A\")\n    defer fmt.Println(\"B\")\n    defer fmt.Println(\"C\")\n    fmt.Println(\"D\")\n}\n",[18,3022,3023,3029,3033,3043,3047,3055,3071,3086,3101,3114],{"__ignoreMap":39},[43,3024,3025,3027],{"class":45,"line":46},[43,3026,391],{"class":188},[43,3028,1912],{"class":175},[43,3030,3031],{"class":45,"line":53},[43,3032,226],{"emptyLinePlaceholder":225},[43,3034,3035,3037,3039,3041],{"class":45,"line":59},[43,3036,406],{"class":188},[43,3038,2540],{"class":178},[43,3040,1929],{"class":175},[43,3042,424],{"class":178},[43,3044,3045],{"class":45,"line":65},[43,3046,226],{"emptyLinePlaceholder":225},[43,3048,3049,3051,3053],{"class":45,"line":71},[43,3050,518],{"class":188},[43,3052,1955],{"class":175},[43,3054,1024],{"class":409},[43,3056,3057,3059,3062,3064,3066,3069],{"class":45,"line":77},[43,3058,2667],{"class":188},[43,3060,3061],{"class":409}," fmt.",[43,3063,2283],{"class":175},[43,3065,524],{"class":409},[43,3067,3068],{"class":178},"\"A\"",[43,3070,460],{"class":409},[43,3072,3073,3075,3077,3079,3081,3084],{"class":45,"line":83},[43,3074,2667],{"class":188},[43,3076,3061],{"class":409},[43,3078,2283],{"class":175},[43,3080,524],{"class":409},[43,3082,3083],{"class":178},"\"B\"",[43,3085,460],{"class":409},[43,3087,3088,3090,3092,3094,3096,3099],{"class":45,"line":89},[43,3089,2667],{"class":188},[43,3091,3061],{"class":409},[43,3093,2283],{"class":175},[43,3095,524],{"class":409},[43,3097,3098],{"class":178},"\"C\"",[43,3100,460],{"class":409},[43,3102,3103,3105,3107,3109,3112],{"class":45,"line":95},[43,3104,2304],{"class":409},[43,3106,2283],{"class":175},[43,3108,524],{"class":409},[43,3110,3111],{"class":178},"\"D\"",[43,3113,460],{"class":409},[43,3115,3116],{"class":45,"line":101},[43,3117,504],{"class":409},[14,3119,3120],{},"What's the output order?",[3122,3123,3124,3128,3136],"details",{},[3125,3126,3127],"summary",{},"Answer",[35,3129,3134],{"className":3130,"code":3132,"language":3133},[3131],"language-text","D\nC\nB\nA\n","text",[18,3135,3132],{"__ignoreMap":39},[14,3137,3138,3139,3142,3143,3146,3147,540,3150,540,3153,3156,3157,3160,3161,540,3164,3167,3168,3171],{},"Deferred functions run in ",[2720,3140,3141],{},"LIFO order"," (last deferred runs first). ",[18,3144,3145],{},"D"," prints immediately, then defers unwind: ",[18,3148,3149],{},"C",[18,3151,3152],{},"B",[18,3154,3155],{},"A",". This is critical for resource cleanup — if you ",[18,3158,3159],{},"defer f.Close()"," then ",[18,3162,3163],{},"defer g.Close()",[18,3165,3166],{},"g"," closes before ",[18,3169,3170],{},"f"," (reverse order). For nested resources, open in order, defer in the same order, and they close in reverse (innermost first) — which is what you want.",[27,3173,3175],{"id":3174},"whats-next","📚 What's Next",[14,3177,3178,3179,3184,3185,3188],{},"→ ",[3180,3181,3183],"a",{"href":3182},"\u002Fgo\u002F03-variables-constants-and-types","03 — Variables, Constants & Types"," — zero-value semantics, untyped constants, ",[18,3186,3187],{},"iota"," bit flags, named types, and the shadowing trap.",[3190,3191,3192],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":39,"searchDepth":53,"depth":53,"links":3194},[3195,3198,3202,3204,3208,3209,3211,3212,3213,3214,3215],{"id":29,"depth":53,"text":30,"children":3196},[3197],{"id":155,"depth":59,"text":156},{"id":359,"depth":53,"text":360,"children":3199},[3200,3201],{"id":713,"depth":59,"text":714},{"id":782,"depth":59,"text":783},{"id":892,"depth":53,"text":3203},"init() — Execution Order and Why It's Dangerous",{"id":1250,"depth":53,"text":3205,"children":3206},"The go Command — Production Subcommands",[3207],{"id":1647,"depth":59,"text":1648},{"id":1769,"depth":53,"text":1770},{"id":1883,"depth":53,"text":3210},"os.Args vs flag vs cobra",{"id":2515,"depth":53,"text":2516},{"id":2711,"depth":53,"text":2712},{"id":2816,"depth":53,"text":2817},{"id":3014,"depth":53,"text":3015},{"id":3174,"depth":53,"text":3175},"Package layout, import resolution, init() ordering, the compilation pipeline, and production go-command flags — beyond hello world.","md",{},"\u002Fgo\u002F02-hello-world-and-go-command",{"title":5,"description":3216},"go\u002F02-hello-world-and-go-command","opJGGK5xBnThAbK3btLmrD_zp7nCLEqNbk50n39DppY",1789924648052]