{"id":"207dd409-b3b0-4871-be29-2bbbc52d5d43","shortId":"jvG3X5","kind":"skill","title":"go-control-flow","tagline":"Use when writing conditionals, loops, or switch statements in Go — including if with initialization, early returns, for loop forms, range, switch, type switches, and blank identifier patterns. Also use when writing a simple if/else or for loop, even if the user doesn't mention gu","description":"# Go Control Flow\n\n> Read [references/SWITCH-PATTERNS.md](references/SWITCH-PATTERNS.md) when using switch statements, type switches, or break with labels\n\n> Read [references/BLANK-IDENTIFIER.md](references/BLANK-IDENTIFIER.md) when using `_`, blank identifier imports, or compile-time interface checks\n\n---\n\n## If with Initialization\n\n`if` and `switch` accept an optional initialization statement. Use it to scope\nvariables to the conditional block:\n\n```go\nif err := file.Chmod(0664); err != nil {\n    log.Print(err)\n    return err\n}\n```\n\nIf you need the variable beyond a few lines after the `if`, declare it\nseparately and use a standard `if` instead:\n\n```go\nx, err := f()\nif err != nil {\n    return err\n}\n// lots of code that uses x\n```\n\n## Indent Error Flow (Guard Clauses)\n\nWhen an `if` body ends with `break`, `continue`, `goto`, or `return`, omit the\nunnecessary `else`. Keep the success path unindented:\n\n```go\nf, err := os.Open(name)\nif err != nil {\n    return err\n}\nd, err := f.Stat()\nif err != nil {\n    f.Close()\n    return err\n}\ncodeUsing(f, d)\n```\n\nNever bury normal flow inside an `else` when the `if` already returns.\n\n---\n\n## Redeclaration and Reassignment\n\nThe `:=` short declaration allows redeclaring variables in the same scope:\n\n```go\nf, err := os.Open(name)  // declares f and err\nd, err := f.Stat()       // declares d, reassigns err\n```\n\nA variable `v` may appear in a `:=` declaration even if already declared,\nprovided:\n\n1. The declaration is in the **same scope** as the existing `v`\n2. The value is **assignable** to `v`\n3. At least **one other variable** is newly created by the declaration\n\n### Variable Shadowing\n\n**Warning**: If `v` is declared in an outer scope, `:=` creates a **new**\nvariable that shadows it — a common source of bugs:\n\n```go\n// Bug: ctx inside the if block shadows the outer ctx\nif *shortenDeadlines {\n    ctx, cancel := context.WithTimeout(ctx, 3*time.Second)\n    defer cancel()\n}\n// ctx here is still the original — the shadowed ctx didn't escape\n\n// Fix: use = instead of :=\nvar cancel func()\nctx, cancel = context.WithTimeout(ctx, 3*time.Second)\n```\n\n---\n\n## For Loops\n\nGo's `for` is its only looping construct, unifying `while`, `do-while`, and\nC-style `for`:\n\n```go\n// Condition-only (Go's \"while\")\nfor x > 0 {\n    x = process(x)\n}\n\n// Infinite loop\nfor {\n    if done() { break }\n}\n\n// C-style three-component\nfor i := 0; i < n; i++ { ... }\n```\n\n### Range\n\n`range` iterates over slices, maps, strings, and channels:\n\n```go\nfor i, v := range slice { ... }   // index + value\nfor k, v := range myMap { ... }   // key + value (non-deterministic order)\nfor i, r := range \"héllo\" { ... } // byte index + rune (not byte)\nfor v := range ch { ... }         // receives until channel closed\n```\n\n**Key rules:**\n- Range over strings yields **runes**, not bytes — `i` is the byte offset\n- Range over maps has **non-deterministic order** — don't rely on it\n- Use `_` to discard the index or value: `for _, v := range slice`\n\n### Parallel Assignment\n\nGo has no comma operator. Use parallel assignment for multiple loop variables:\n\n```go\nfor i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {\n    a[i], a[j] = a[j], a[i]\n}\n```\n\n`++` and `--` are statements, not expressions — they cannot appear in parallel\nassignment.\n\n---\n\n## Switch: Labeled Break\n\n`break` inside a `switch` within a `for` loop only breaks the switch.\nUse a labeled `break` to exit the enclosing loop:\n\n```go\nLoop:\n    for _, v := range items {\n        switch v.Type {\n        case \"done\":\n            break Loop  // breaks the for loop\n        }\n    }\n```\n\nFor type switches, see **go-interfaces**: Type Switch.\n\n---\n\n## The Blank Identifier\n\n**Never discard errors carelessly** — a nil dereference panic may follow.\n\nVerify interface compliance at compile time: `var _ io.Writer = (*MyType)(nil)`.\nSee **go-interfaces** for the interface satisfaction check pattern.\n\n---\n\n## Quick Reference\n\n| Pattern | Go Idiom |\n|---------|----------|\n| If initialization | `if err := f(); err != nil { }` |\n| Early return | Omit `else` when if body returns |\n| Redeclaration | `:=` reassigns if same scope + new var |\n| Shadowing trap | `:=` in inner scope creates new variable |\n| Parallel assignment | `i, j = i+1, j-1` |\n| Expression-less switch | `switch { case cond: }` |\n| Comma cases | `case 'a', 'b', 'c':` |\n| No fallthrough | Default behavior (explicit `fallthrough` if needed) |\n| Break from loop in switch | `break Label` |\n| Discard value | `_, err := f()` |\n| Side-effect import | `import _ \"pkg\"` |\n| Interface check | `var _ Interface = (*Type)(nil)` |\n\n---\n\n## Related Skills\n\n- **Error flow**: See [go-error-handling](../go-error-handling/SKILL.md) when structuring guard clauses, early returns, or error-first patterns\n- **Type switches**: See [go-interfaces](../go-interfaces/SKILL.md) when using type switches, the comma-ok idiom, or interface satisfaction checks\n- **Nesting reduction**: See [go-style-core](../go-style-core/SKILL.md) when reducing nesting depth or resolving formatting questions\n- **Variable scoping**: See [go-declarations](../go-declarations/SKILL.md) when using if-init, `:=` redeclaration, or reducing variable scope","tags":["control","flow","golang","skills","cxuu","agent-skills","ai-agent","ai-assistant","claude","claude-code","codex","cursor"],"capabilities":["skill","source-cxuu","skill-go-control-flow","topic-agent-skills","topic-ai-agent","topic-ai-assistant","topic-claude","topic-claude-code","topic-codex","topic-cursor","topic-golang","topic-llm"],"categories":["golang-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cxuu/golang-skills/go-control-flow","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cxuu/golang-skills","source_repo":"https://github.com/cxuu/golang-skills","install_from":"skills.sh"}},"qualityScore":"0.491","qualityRationale":"deterministic score 0.49 from registry signals: · indexed on github topic:agent-skills · 82 github stars · SKILL.md body (5,160 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T12:55:17.765Z","embedding":null,"createdAt":"2026-04-18T22:13:09.264Z","updatedAt":"2026-05-02T12:55:17.765Z","lastSeenAt":"2026-05-02T12:55:17.765Z","tsv":"'+1':510,654 '-1':504,512,656 '/go-declarations/skill.md':764 '/go-error-handling/skill.md':710 '/go-interfaces/skill.md':728 '/go-style-core/skill.md':749 '0':377,395,501 '0664':104 '1':248 '2':260 '3':267,319,346 'accept':86 'allow':212 'alreadi':204,245 'also':32 'appear':239,528 'assign':264,484,492,531,650 'b':668 'behavior':673 'beyond':116 'blank':29,71,582 'block':99,308 'bodi':155,632 'break':63,158,386,534,535,544,550,566,568,678,683 'bug':301,303 'buri':195 'byte':432,436,453,457 'c':365,388,669 'c-style':364,387 'cancel':316,322,340,343 'cannot':527 'careless':587 'case':564,662,665,666 'ch':440 'channel':407,443 'check':79,612,696,741 'claus':151,714 'close':444 'code':143 'codeus':191 'comma':488,664,735 'comma-ok':734 'common':298 'compil':76,598 'compile-tim':75 'complianc':596 'compon':392 'cond':663 'condit':8,98,370 'condition-on':369 'construct':357 'context.withtimeout':317,344 'continu':159 'control':3,51 'core':748 'creat':275,290,646 'ctx':304,312,315,318,323,331,342,345 'd':182,193,228,232 'declar':123,211,224,231,242,246,250,278,285,763 'default':672 'defer':321 'depth':753 'derefer':590 'determinist':425,465 'didn':332 'discard':474,585,685 'do-whil':360 'doesn':46 'done':385,565 'earli':19,626,715 'effect':691 'els':166,200,629 'enclos':554 'end':156 'err':102,105,108,110,134,137,140,174,178,181,183,186,190,221,227,229,234,622,624,687 'error':148,586,703,708,719 'error-first':718 'escap':334 'even':42,243 'exist':258 'exit':552 'explicit':674 'express':525,658 'expression-less':657 'f':135,173,192,220,225,623,688 'f.close':188 'f.stat':184,230 'fallthrough':671,675 'file.chmod':103 'first':720 'fix':335 'flow':4,52,149,197,704 'follow':593 'form':23 'format':756 'func':341 'go':2,14,50,100,132,172,219,302,350,368,372,408,485,497,556,577,606,617,707,726,746,762 'go-control-flow':1 'go-declar':761 'go-error-handl':706 'go-interfac':576,605,725 'go-style-cor':745 'goto':160 'gu':49 'guard':150,713 'handl':709 'héllo':431 'identifi':30,72,583 'idiom':618,737 'if-init':767 'if/else':38 'import':73,692,693 'includ':15 'indent':147 'index':414,433,476 'infinit':381 'init':769 'initi':18,82,89,620 'inner':644 'insid':198,305,536 'instead':131,337 'interfac':78,578,595,607,610,695,698,727,739 'io.writer':601 'item':561 'iter':401 'j':500,506,508,511,516,518,652,655 'k':417 'keep':167 'key':421,445 'label':65,533,549,684 'least':269 'len':502 'less':659 'line':119 'log.print':107 'loop':9,22,41,349,356,382,495,542,555,557,567,571,680 'lot':141 'map':404,461 'may':238,592 'mention':48 'multipl':494 'mymap':420 'mytyp':602 'n':397 'name':176,223 'need':113,677 'nest':742,752 'never':194,584 'new':292,639,647 'newli':274 'nil':106,138,179,187,589,603,625,700 'non':424,464 'non-determinist':423,463 'normal':196 'offset':458 'ok':736 'omit':163,628 'one':270 'oper':489 'option':88 'order':426,466 'origin':328 'os.open':175,222 'outer':288,311 'panic':591 'parallel':483,491,530,649 'path':170 'pattern':31,613,616,721 'pkg':694 'process':379 'provid':247 'question':757 'quick':614 'r':429 'rang':24,399,400,412,419,430,439,447,459,481,560 'read':53,66 'reassign':208,233,635 'receiv':441 'redeclar':206,213,634,770 'reduc':751,772 'reduct':743 'refer':615 'references/blank-identifier.md':67,68 'references/switch-patterns.md':54,55 'relat':701 'reli':469 'resolv':755 'return':20,109,139,162,180,189,205,627,633,716 'rule':446 'rune':434,451 'satisfact':611,740 'scope':94,218,255,289,638,645,759,774 'see':575,604,705,724,744,760 'separ':125 'shadow':280,295,309,330,641 'short':210 'shortendeadlin':314 'side':690 'side-effect':689 'simpl':37 'skill':702 'skill-go-control-flow' 'slice':403,413,482 'sourc':299 'source-cxuu' 'standard':129 'statement':12,59,90,523 'still':326 'string':405,449 'structur':712 'style':366,389,747 'success':169 'switch':11,25,27,58,61,85,532,538,546,562,574,580,660,661,682,723,732 'three':391 'three-compon':390 'time':77,599 'time.second':320,347 'topic-agent-skills' 'topic-ai-agent' 'topic-ai-assistant' 'topic-claude' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-golang' 'topic-llm' 'trap':642 'type':26,60,573,579,699,722,731 'unifi':358 'unind':171 'unnecessari':165 'use':5,33,57,70,91,127,145,336,472,490,547,730,766 'user':45 'v':237,259,266,283,411,418,438,480,559 'v.type':563 'valu':262,415,422,478,686 'var':339,600,640,697 'variabl':95,115,214,236,272,279,293,496,648,758,773 'verifi':594 'warn':281 'within':539 'write':7,35 'x':133,146,376,378,380 'yield':450","prices":[{"id":"121bf9b3-4b33-4696-9f95-0cedea2e85f8","listingId":"207dd409-b3b0-4871-be29-2bbbc52d5d43","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cxuu","category":"golang-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:13:09.264Z"}],"sources":[{"listingId":"207dd409-b3b0-4871-be29-2bbbc52d5d43","source":"github","sourceId":"cxuu/golang-skills/go-control-flow","sourceUrl":"https://github.com/cxuu/golang-skills/tree/main/skills/go-control-flow","isPrimary":false,"firstSeenAt":"2026-04-18T22:13:09.264Z","lastSeenAt":"2026-05-02T12:55:17.765Z"}],"details":{"listingId":"207dd409-b3b0-4871-be29-2bbbc52d5d43","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cxuu","slug":"go-control-flow","github":{"repo":"cxuu/golang-skills","stars":82,"topics":["agent-skills","ai-agent","ai-assistant","claude","claude-code","codex","cursor","go","golang","llm"],"license":"apache-2.0","html_url":"https://github.com/cxuu/golang-skills","pushed_at":"2026-03-15T19:32:10Z","description":"AI Agent Skills for idiomatic, production-ready Go code, distilled from Google, Uber, Community","skill_md_sha":"1c70b9a94a8eb89806b4e4f907c3929f46293d7c","skill_md_path":"skills/go-control-flow/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cxuu/golang-skills/tree/main/skills/go-control-flow"},"layout":"multi","source":"github","category":"golang-skills","frontmatter":{"name":"go-control-flow","license":"Apache-2.0","description":"Use when writing conditionals, loops, or switch statements in Go — including if with initialization, early returns, for loop forms, range, switch, type switches, and blank identifier patterns. Also use when writing a simple if/else or for loop, even if the user doesn't mention guard clauses or variable scoping. Does not cover error flow patterns (see go-error-handling)."},"skills_sh_url":"https://skills.sh/cxuu/golang-skills/go-control-flow"},"updatedAt":"2026-05-02T12:55:17.765Z"}}