All skills
cxuu avatar

/go-control-flow

@91f0c2e
by Charles Xucxuu/golang-skills165 stars
19

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).

Use this Skill: https://skilld.dev/gh/cxuu/golang-skills/go-control-flow

This session only. Nothing lands on disk.

SKILL.md

≈98 tokens always: the name and description. ≈1.3k when used: this file. ≈1.1k more on demand in 2 files.

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:

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

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:

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:

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:

// 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:

// 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:

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:

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:

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.


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 when structuring guard clauses, early returns, or error-first patterns
  • Type switches: See go-interfaces when using type switches, the comma-ok idiom, or interface satisfaction checks
  • Nesting reduction: See go-style-core when reducing nesting depth or resolving formatting questions
  • Variable scoping: See go-declarations when using if-init, := redeclaration, or reducing variable scope

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides safe and idiomatic guidelines for writing control flow structures in Go, such as loops, conditionals, switch statements, and blank identifiers. No security risks or malicious patterns were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    1 file scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 91f0c2e. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 3 months ago

README badge

README badge for cxuu/golang-skills/go-control-flow