Agent Skills

go-control-flow

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

Install

npx skills add https://github.com/cxuu/golang-skills --skill go-control-flow
SKILL.md

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

Related skills

entra-app-registrationmicrosoft606KGuides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.azure-messagingmicrosoft595KTroubleshoot and resolve issues with Azure Messaging SDKs for Event Hubs and Service Bus. Covers connection failures, authentication errors, message processing issues, and SDK configuration problems. WHEN: event hub SDK error, service bus SDK issue, messaging connection failure, AMQP error, event processor host issue, message lock lost, message lock expired, lock renewal, lock renewal batch, send timeout, receiver disconnected, SDK troubleshooting, azure messaging SDK, event hub consumer, servicentra-agent-idmicrosoft328KProvision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmi_path, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmi_path token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registsupabasesupabase298KUse when doing ANY task involving Supabase. Triggers: Supabase products (Database, Auth, Edge Functions, Realtime, Storage, Vectors, Cron, Queues); client libraries and SSR integrations (supabase-js, @supabase/ssr) in Next.js, React, SvelteKit, Astro, Remix; auth issues (login, logout, sessions, JWT, cookies, getSession, getUser, getClaims, RLS); Supabase CLI or MCP server; schema changes, migrations, declarative schemas, security audits, Postgres extensions (pg_graphql, pg_cron, pg_vector); deb

Search skills and MCP servers

Fuzzy search across 23,137 skills and servers