go-control-flow — Claude Code skill: what it does, how to install
Teaches AI agents canonical Go control flow patterns: early returns, scoped if statements, and for loops. Keeps code flat and avoids variable shadowing bugs.
npx skills add cxuu/golang-skills --skill go-control-flow -a claude-codeWhat go-control-flow does
The skill instructs coding agents on idiomatic Go control flow. It enforces if statements with initialization statements to restrict variable scope and strips redundant else blocks when returning early. It covers all Go for loop forms, parallel assignments for two-pointer traversals, rune iteration over strings, and labeled breaks to exit loops from within a switch.
A key warning targets variable shadowing. Using := inside an inner block silently creates a new variable instead of reassigning the outer one. This frequently causes lost context updates. Error handling patterns are explicitly excluded here and redirected to go-error-handling.
What it helps with
- flatten nested conditionals using guard clauses and early returns
- break out of an outer loop from an inner switch statement
- scope transient variables directly within if or switch initialization
- prevent variable shadowing bugs caused by inner-scope
:=declarations
Example prompts for the agent
- Refactor this nested if-else chain into clean Go guard clauses
- Write a two-pointer reverse loop using Go parallel assignment
- Check this switch statement inside a for loop for exit bugs
How to install go-control-flow
1Skills CLI (Vercel)
npx skills add cxuu/golang-skills --skill go-control-flow -a claude-code2Manually: put the files in place
~/.claude/skills/go-control-flow/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/go-control-flow/
1Skills CLI (Vercel)
npx skills add cxuu/golang-skills --skill go-control-flow -a codex2Manually: put the files in place
.agents/skills/go-control-flow/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add cxuu/golang-skills --skill go-control-flow -a cursor2Manually: put the files in place
.cursor/skills/go-control-flow/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install cxuu/golang-skills go-control-flow2Manually: put the files in place
.github/skills/go-control-flow/SKILL.md1Skills CLI (Vercel)
npx skills add cxuu/golang-skills --skill go-control-flow -a gemini-cli2Platform CLI
gemini skills install https://github.com/cxuu/golang-skills --path skills/go-control-flowManually: put the files in place
.devin/skills/go-control-flow/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add cxuu/golang-skills --skill go-control-flow -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about go-control-flow
How do I install go-control-flow in Claude Code?
Run npx skills add cxuu/golang-skills --skill go-control-flow -a claude-code. The skill file is placed in ~/.claude/skills/go-control-flow/SKILL.md.
What does go-control-flow do?
It provides idiomatic guidance on Go control structures. It covers scoped initialization, range behaviors, labeled breaks, and avoiding accidental shadowing.
Does go-control-flow handle Go error patterns?
No. Error handling flow and early guard return patterns for errors are delegated to the separate go-error-handling skill.
Source text
SKILL.md · Apache-2.0
---
name: go-control-flow
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).
---
# Go Control Flow
## Resource Routing
- `references/SWITCH-PATTERNS.md` - Read when using switch statements, type switches, fallthrough, or labeled breaks.
- `references/BLANK-IDENTIFIER.md` - Read when using `_`, blank imports, unused compile-time assertions, or intentional discards.
---
## If with Initialization
`if` and `switch` accept an optional initialization statement. Use it to scope
variables to the conditional block:
```go
if err := file.Chmod(0664); err != nil {
log.Print(err)
return err
}
```
If you need the variable beyond a few lines after the `if`, declare it
separately and use a standard `if` instead:
```go
x, err := f()
if err != nil {
return err
}
// lots of code that uses x
```
## Indent Error Flow (Guard Clauses)
When an `if` body ends with `break`, `continue`, `goto`, or `return`, omit the
unnecessary `else`. Keep the success path unindented:
```go
f, err := os.Open(name)
if err != nil {
return err
}
d, err := f.Stat()
if err != nil {
f.Close()
return err
}
codeUsing(f, d)
```
Never bury normal flow inside an `else` when the `if` already returns.
---
## Redeclaration and Reassignment
The `:=` short declaration allows redeclaring variables in the same scope:
```go
f, err := os.Open(name) // declares f and err
d, err := f.Stat() // declares d, reassigns err
```
A variable `v` may appear in a `:=` declaration even if already declared,
provided:
1. The declaration is in the **same scope** as the existing `v`
2. The value is **assignable** to `v`
3. At least **one other variable** is newly created by the declaration
### Variable Shadowing
**Warning**: If `v` is declared in an outer scope, `:=` creates a **new**
variable that shadows it — a common source of bugs:
```go
// Bug: ctx inside the if block shadows the outer ctx
if *shortenDeadlines {
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()
}
// ctx here is still the original — the shadowed ctx didn't escape
// Fix: use = instead of :=
var cancel func()
ctx, cancel = context.WithTimeout(ctx, 3*time.Second)
```
---
## For Loops
Go's `for` is its only looping construct, unifying `while`, `do-while`, and
C-style `for`:
```go
// Condition-only (Go's "while")
for x > 0 {
x = process(x)
}
// Infinite loop
for {
if done() { break }
}
// C-style three-component
for i := 0; i < n; i++ { ... }
```
### Range
`range` iterates over slices, maps, strings, and channels:
```go
for i, v := range slice { ... } // index + value
for k, v := range myMap { ... } // key + value (non-deterministic order)
for i, r := range "héllo" { ... } // byte index + rune (not byte)
for v := range ch { ... } // receives until channel closed
```
**Key rules:**
- Range over strings yields **runes**, not bytes — `i` is the byte offset
- Range over maps has **non-deterministic order** — don't rely on it
- Use `_` to discard the index or value: `for _, v := range slice`
### Parallel Assignment
Go has no comma operator. Use parallel assignment for multiple loop variables:
```go
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
```
`++` and `--` are statements, not expressions — they cannot appear in parallel
assignment.
---
## Switch: Labeled Break
`break` inside a `switch` within a `for` loop only breaks the switch.
Use a labeled `break` to exit the enclosing loop:
```go
Loop:
for _, v := range items {
switch v.Type {
case "done":
break Loop // breaks the for loop
}
}
```
For type switches, see **go-interfaces**: Type Switch.
---
## The Blank Identifier
**Never discard errors carelessly** — a nil dereference panic may follow.
Route compile-time interface assertions to [go-interfaces](../go-interfaces/SKILL.md).
---
## Quick Reference
| Pattern | Go Idiom |
|---------|----------|
| If initialization | `if err := f(); err != nil { }` |
| Early return | Omit `else` when if body returns |
| Redeclaration | `:=` reassigns if same scope + new var |
| Shadowing trap | `:=` in inner scope creates new variable |
| Parallel assignment | `i, j = i+1, j-1` |
| Expression-less switch | `switch { case cond: }` |
| Comma cases | `case 'a', 'b', 'c':` |
| No fallthrough | Default behavior (explicit `fallthrough` if needed) |
| Break from loop in switch | `break Label` |
| Discard value | `_, err := f()` |
| Side-effect import | `import _ "pkg"` |
| Interface check | Route to go-interfaces |
---
## Related Skills
- **Error flow**: See [go-error-handling](../go-error-handling/SKILL.md) when structuring guard clauses, early returns, or error-first patterns
- **Type switches**: See [go-interfaces](../go-interfaces/SKILL.md) when using type switches, the comma-ok idiom, or interface satisfaction checks
- **Nesting reduction**: See [go-style-core](../go-style-core/SKILL.md) when reducing nesting depth or resolving formatting questions
- **Variable scoping**: See [go-declarations](../go-declarations/SKILL.md) when using if-init, `:=` redeclaration, or reducing variable scope
© cxuu · Apache-2.0 · cxuu/golang-skills