go-clean-architecture
Use when scaffolding or refactoring a Go service into a framework-agnostic clean (hexagonal) architecture: Domain, Usecase,…
Use when declaring or initializing Go variables, constants, structs, or maps. Covers var vs :=, grouped declaration blocks, iota enums starting at 1, struct/map/slice composite literals, raw string literals, `any` over `interface{}`, and avoiding shadowed builtins. Apply
Claude Code
$ npx -y skills add muratmirgun/gophers --skill go-declarations --agent claude-code
Codex
$ npx skills add muratmirgun/gophers --skill go-declarations -a codex -y
Cursor
$ npx skills add muratmirgun/gophers --skill go-declarations -a cursor -y
Gemini CLI
$ npx skills add muratmirgun/gophers --skill go-declarations -a gemini-cli -y
GitHub Copilot
$ npx skills add muratmirgun/gophers --skill go-declarations -a github-copilot -y
OpenCode
$ npx skills add muratmirgun/gophers --skill go-declarations -a opencode -y
Windsurf
$ npx skills add muratmirgun/gophers --skill go-declarations -a windsurf -y
name: go-declarations
description: "Use when declaring or initializing Go variables, constants, structs, or maps. Covers var vs :=, grouped declaration blocks, iota enums starting at 1, struct/map/slice composite literals, raw string literals, `any` over `interface{}`, and avoiding shadowed builtins. Apply proactively to any new struct, const block, or top-level var, even if the user did not ask about declaration style. Does not cover identifier naming (see go-naming)."
license: MIT
compatibility: "Designed for Claude Code or similar AI coding agents. `any` requires Go 1.18+."
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*)Pick the simplest declaration form that expresses your intent: scope variables tightly, group related declarations, and let the zero value do its job.
1. **`:=` for locals with values; `var` for intentional zero values or top-level declarations.** 2. **Group related declarations in parenthesized blocks.** Separate unrelated ones into distinct blocks. 3. **Start enums at `iota + 1`** so the zero value is "invalid/unset" — unless zero is genuinely meaningful. 4. **Initialize structs with field names.** Omit zero-value fields; let defaults speak. 5. **Use `any`, not `interface{}`,** in all new code. 6. **Never shadow builtins** (`len`, `cap`, `error`, `new`, `make`, `copy`, `any`, `nil`, ...).
| Context | Use | Example | |---|---|---| | Package-level | `var` (always) | `var startTime = time.Now()` | | Local with computed value | `:=` | `s := "foo"` | | Local zero-value, intentional | `var` | `var filtered []int` | | Declared type differs from RHS | `var T = expr` | `var e error = f()` |
> Read [references/scope-and-shadowing.md](references/scope-and-shadowing.md) when fighting subtle bugs caused by `:=` redeclaring an outer variable.
// Bad
const a = 1
const b = 2
// Good
const (
a = 1
b = 2
)Inside functions, group adjacent vars even if loosely related:
var (
caller = c.name
format = "json"
timeout = 5 * time.Second
)Zero is the default; reserve it for "uninitialized" by starting enums at `iota + 1`:
type Operation int
const (
Add Operation = iota + 1 // 1
Subtract // 2
Multiply // 3
)Use plain `iota` only when the zero value is the sensible default (e.g., `LogToStdout = iota`).
> Read [references/iota-and-literals.md](references/iota-and-literals.md) for bitmask enums, `String()` methods, raw strings, and composite-literal formatting.
u := User{Name: "Ada", Email: "ada@example.com"}
sptr := &Config{Timeout: 5 * time.Second}
var empty Buffer // zero value, ready to useTest tables with ≤3 fields may use positional literals when the meaning is obvious.
| Scenario | Use | Example | |---|---|---| | Empty, will be populated | `make(map[K]V)` | `m := make(map[string]int)` | | Nil, lazily allocated | `var` | `var m map[string]int` | | Known entries up front | Literal | `m := map[string]int{"a": 1}` |
`make` signals "initialized but empty" — different from a nil map (which panics on write). Provide a size hint when the count is known: `make(map[K]V, n)`.
Use backticks to avoid escape gymnastics:
// Bad re := "^\\s*name:\\s*\"(.*)\"" // Good re := `^\s*name:\s*"(.*)"`
Ideal for regex, SQL, JSON, and multi-line text.
// Old
func Print(v interface{}) { ... }
// New
func Print(v any) { ... }`any` is an alias for `interface{}` since Go 1.18 — same type, less noise.
The predeclared identifiers (`error`, `string`, `len`, `cap`, `append`, `copy`, `new`, `make`, `close`, `delete`, `panic`, `recover`, `any`, `true`, `false`, `nil`, `iota`) are not reserved words — Go lets you shadow them. Don't.
// Bad — shadows the builtin error type var error string // Good var errorMessage string
`go vet` catches the most common cases.
> Read [references/structs-and-tags.md](references/structs-and-tags.md) when designing struct fields that cross a serialization boundary (JSON, YAML, protobuf), embedding types, or formatting many-field literals.
| Anti-pattern | Why it hurts | Do this instead | |---|---|---| | `u := User{}` for a zero value | Misleads readers into expecting non-defaults | `var u User` | | `new(T)` then assign fields | Two-step where one works | `&T{Field: v}` | | Positional struct literals (>3 fields) | Silent breakage on field reordering | Use field names | | `iota` starting at 0 for an enum | Zero value collides with a real case | `iota + 1` | | `var m map[string]int` then `m[k] = v` | Panic on nil map write | `m := make(map[string]int)` | | Hand-escaped JSON or regex strings | Hard to read, easy to mistype | Raw string literal | | `interface{}` in new code | Verbose, outdated | `any` |
-
26 production-grade Go skills for Claude Code, Gemini CLI, and opencode. Battle-tested patterns from the Go community — codified as triggerable AI skills.
Use when scaffolding or refactoring a Go service into a framework-agnostic clean (hexagonal) architecture: Domain, Usecase,…
Invoke this skill to systematically review a Go change against community style standards before merging. Walks the diff topic by…
Use when writing or reviewing Go code for clarity, formatting, control flow, variable declarations, switch usage, and function…
Use when writing or reviewing concurrent Go code — goroutines, channels, select, mutexes, atomics, errgroup, singleflight, worker…
Use when designing, propagating, or debugging context.Context flow in Go — first-parameter placement, deadlines and cancellation,…
Use when writing conditionals, loops, switches, type switches, or blank-identifier patterns in Go. Covers if-with-initialization,…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.