From golang-skills
Guides Go control flow best practices: if with init, guard clauses/early returns, for/range loops, switches/type switches, blank identifier, redeclaration/shadowing rules.
npx claudepluginhub cxuu/golang-skills --plugin golang-skillsThis skill uses the workspace's default tool permissions.
> Read [references/SWITCH-PATTERNS.md](references/SWITCH-PATTERNS.md) when using switch statements, type switches, or break with labels
Guides Go declarations and initialization: var vs :=, grouping vars/consts, iota enums, if-init scoping, struct field-named init, composite literal formatting.
Enforces Go code style for clarity: semantic line breaking beyond 120 chars, var vs := declarations, explicit slice/map initialization, field-named composite literals. Use for writing/reviewing Go code.
Provides idiomatic Go patterns and best practices for error handling, concurrency like worker pools, simplicity, zero values, and interfaces. Activates for writing, reviewing, refactoring, or designing Go code.
Share bugs, ideas, or general feedback.
Read references/SWITCH-PATTERNS.md when using switch statements, type switches, or break with labels
Read references/BLANK-IDENTIFIER.md when using
_, blank identifier imports, or compile-time interface checks
if and switch accept an optional initialization statement. Use it to scope
variables to the conditional block:
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:
x, err := f()
if err != nil {
return err
}
// lots of code that uses x
When an if body ends with break, continue, goto, or return, omit the
unnecessary else. Keep the success path unindented:
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.
The := short declaration allows redeclaring variables in the same scope:
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:
vvWarning: If v is declared in an outer scope, := creates a new
variable that shadows it — a common source of bugs:
// 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)
Go's for is its only looping construct, unifying while, do-while, and
C-style for:
// 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 iterates over slices, maps, strings, and channels:
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:
i is the byte offset_ to discard the index or value: for _, v := range sliceGo has no comma operator. Use parallel assignment for multiple loop variables:
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.
break inside a switch within a for loop only breaks the switch.
Use a labeled break to exit the enclosing loop:
Loop:
for _, v := range items {
switch v.Type {
case "done":
break Loop // breaks the for loop
}
}
For type switches, see go-interfaces: Type Switch.
Never discard errors carelessly — a nil dereference panic may follow.
Verify interface compliance at compile time: var _ io.Writer = (*MyType)(nil).
See go-interfaces for the interface satisfaction check pattern.
| 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 | var _ Interface = (*Type)(nil) |
:= redeclaration, or reducing variable scope