
Go Control Flow
Apply idiomatic Go blank identifier patterns when discarding values, side-effect imports, or compile-time interface checks in backend code.
Overview
Go control flow is an agent skill for the Build phase that teaches blank identifier (`_`) patterns for safe discards, side-effect imports, and compile-time interface checks in Go.
Install
npx skills add https://github.com/cxuu/golang-skills --skill go-control-flowWhat is this skill?
- Documents `_` for discarding unwanted values in multi-return calls such as os.Stat
- Warns against careless error discards that cause nil-pointer panics, with documented exceptions
- Shows side-effect imports for registering HTTP handlers, image decoders, and similar init wiring
- Includes compile-time interface compliance checks via var _ io.Writer = (*MyType)(nil)
- Small focused reference slice from a golang-skills bundle (blank identifier patterns)
Adoption & trust: 648 installs on skills.sh; 110 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Go code misuses `_` or ignores errors, leading to panics or undetected missing interface methods at compile time.
Who is it for?
Indie developers implementing Go APIs or CLI tools who want quick, correct `_` usage at the keyboard.
Skip if: Learners who need full Go control-flow tutorials (for/select/switch) rather than blank-identifier reference snippets.
When should I use this skill?
User is writing or reviewing Go code involving `_` for discards, side-effect-only imports, or interface satisfaction compile-time checks.
What do I get? / Deliverables
You apply documented blank identifier patterns so discarded values, init-only imports, and interface checks match idiomatic, safer Go backend style.
- Idiomatic blank identifier usage in suggested or edited Go code
- Compile-time interface compliance assertions where appropriate
Recommended Skills
Journey fit
Blank identifier guidance is reference material you reach for while implementing Go services and CLIs, not during launch or growth workflows. Backend is the canonical shelf because the patterns address errors, package init side effects, and interface satisfaction in server and library code.
How it compares
Focused Go idiom reference for `_`—not a linter replacement or generic debugging methodology skill.
Common Questions / FAQ
Who is go-control-flow for?
Solo builders shipping Go backends or CLI tools who want agent guidance on blank identifier patterns while coding or reviewing.
When should I use go-control-flow?
Use it during Build backend work when handling multi-value returns, side-effect imports, or verifying interface implementation in Go source.
Is go-control-flow safe to install?
Review the Security Audits panel on this Prism page; the skill is documentation-only pattern guidance with no prescribed shell or network actions.
SKILL.md
READMESKILL.md - Go Control Flow
# Blank Identifier Patterns The blank identifier `_` serves multiple roles in Go: discarding unwanted values, importing packages for side effects, and verifying interface compliance at compile time. --- ## Multiple Assignment Use `_` to discard unwanted values from multi-value expressions: ```go if _, err := os.Stat(path); os.IsNotExist(err) { fmt.Printf("%s does not exist\n", path) } ``` ### Never Discard Errors Carelessly Silently discarding an error invites nil-pointer panics: ```go // Bad: ignoring error will crash if path doesn't exist fi, _ := os.Stat(path) if fi.IsDir() { ... } // nil pointer dereference ``` If you truly don't need the error, document why: ```go _ = logger.Sync() // best-effort flush; error is non-actionable ``` --- ## Import for Side Effect Import a package solely for its `init()` side effects using the blank identifier: ```go import _ "net/http/pprof" // registers HTTP handlers import _ "image/png" // registers PNG decoder ``` This is commonly used to register drivers, codecs, or debug handlers that wire themselves into a registry during `init()`. --- ## Interface Compliance Check Verify at compile time that a type implements an interface by assigning a nil pointer to a blank-identifier variable of the interface type: ```go var _ io.Writer = (*MyType)(nil) ``` This produces a compile error if `*MyType` does not satisfy `io.Writer`, catching missing methods before runtime. **When to use**: Place this check in the same file that defines the type, typically right after the type declaration. It is especially useful when a type must satisfy an interface defined in another package. See [go-interfaces](../../go-interfaces/SKILL.md): Interface Satisfaction Checks for full guidance on when and where to use this pattern. --- ## Quick Reference | Pattern | Syntax | |---------|--------| | Discard value | `_, err := f()` | | Discard in if-init | `if _, err := f(); err != nil { }` | | Side-effect import | `import _ "pkg"` | | Interface check | `var _ Interface = (*Type)(nil)` | # Switch Patterns Detailed patterns for Go `switch` statements, including expression-less switches, comma cases, break behavior, and labeled breaks. --- ## No Automatic Fallthrough Go `switch` cases do **not** fall through by default (unlike C/Java). Each case body implicitly breaks. Use `fallthrough` only when explicitly needed — it is rare in idiomatic Go. ```go switch n { case 1: fmt.Println("one") // no fallthrough — next case is NOT executed case 2: fmt.Println("two") } ``` --- ## Expression-less Switch A `switch` with no expression switches on `true`. Use it for clean if-else-if chains when comparing a single variable against multiple conditions: ```go func unhex(c byte) byte { switch { case '0' <= c && c <= '9': return c - '0' case 'a' <= c && c <= 'f': return c - 'a' + 10 case 'A' <= c && c <= 'F': return c - 'A' + 10 } return 0 } ``` --- ## Comma-Separated Cases Multiple values can share a single case body using commas — no need for `fallthrough`: ```go func shouldEscape(c byte) bool { switch c { case ' ', '?', '&', '=', '#', '+', '%': return true } return false } ``` --- ## Break with Labels `break` inside a `switch` terminates only the switch, **not** an enclosing `for` loop. Use a label to break out of the loop: ```go Loop: for n := 0; n < len(src); n += size { switch { case src[n] < sizeOne: break // breaks switch only case src[n] < sizeTwo: if n+1 >= len(src) { break Loop // breaks out of for loop } } } ``` Another common pattern — breaking a range loop from inside a switch: ```go Loop: for _, v := range items { switch v.Type { case "done": break Loop // breaks the for loop case "skip": break // breaks only the switch } } ``