go-clean-architecture
Use when scaffolding or refactoring a Go service into a framework-agnostic clean (hexagonal) architecture: Domain, Usecase, Repository, Delivery layers, inward…
Use when writing or reviewing Go code for clarity, formatting, control flow, variable declarations, switch usage, and function design. Covers the priority order (clarity > simplicity > concision > maintainability > consistency), gofmt rules, early-return / no-else patterns,
$ npx -y skills add muratmirgun/gophers --skill go-code-style --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/go-code-styleContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when writing or reviewing Go code for clarity, formatting, control flow, variable declarations, switch usage, and function design. Covers the priority order (clarity > simplicity > concision > maintainability > consistency), gofmt rules, early-return / no-else patterns,
name: go-code-style description: "Use when writing or reviewing Go code for clarity, formatting, control flow, variable declarations, switch usage, and function design. Covers the priority order (clarity > simplicity > concision > maintainability > consistency), gofmt rules, early-return / no-else patterns, switch over if-else chains, slice/map initialization, and value-vs-pointer choices. Apply proactively to every Go change, even when the user has not asked about style." license: MIT compatibility: "Designed for Claude Code or similar AI coding agents. Works on any Go version supported by gofmt; range-over-int requires Go 1.22+." allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*)
`gofmt` handles the mechanical layout. This skill covers the decisions a formatter cannot make: where to break complexity, when to invert an `if`, when a `switch` beats an `else if` chain, and how to pick value vs pointer arguments. The rule of thumb is the Go Proverb: **clear is better than clever**.
1. **Run `gofmt`/`goimports`.** No exceptions, no debates. 2. **Handle errors and edge cases first**, return early, keep the happy path at minimum indentation. 3. **Eliminate unnecessary `else`** when the `if` body ends in `return`/`break`/`continue`. 4. **Prefer `switch` over `if`/`else if` chains** that compare the same value. 5. **Initialize slices and maps explicitly**, never let a nil map reach a write. 6. **Pass small values; pass pointers when mutating or when the type is large (~128B+).**
Apply in this order when two principles collide.
| Priority | Question | Beats | |---|---|---| | 1. Clarity | Can a reader understand intent without extra context? | everything else | | 2. Simplicity | Is this the simplest expression of the idea? | concision, consistency | | 3. Concision | Does every line earn its place? | consistency | | 4. Maintainability | Will this be safe to modify? | consistency | | 5. Consistency | Does it match nearby code? | — |
A "consistent" piece of bad code is still bad code. Clarity wins.
> Read [references/formatting-and-layout.md](references/formatting-and-layout.md) for line-breaking, multi-line signatures, file/declaration order.
func process(data []byte) (*Result, error) {
if len(data) == 0 {
return nil, errors.New("empty data")
}
parsed, err := parse(data)
if err != nil {
return nil, fmt.Errorf("parsing: %w", err)
}
return transform(parsed), nil
}When the `if` body unconditionally exits (`return`/`break`/`continue`), drop the `else`. For assignments, prefer default-then-override:
// Good
lvl := slog.LevelInfo
if debug {
lvl = slog.LevelDebug
}When all branches compare the same value, `switch` makes intent explicit and `exhaustive` can verify completeness:
switch status {
case StatusActive:
activate()
case StatusInactive:
deactivate()
case StatusPaused:
pause()
default:
panic(fmt.Sprintf("unexpected status: %d", status))
}A tagless `switch` replaces a chain of unrelated `if/else if` conditions — first matching case wins.
When an `if` has 3+ operands, hoist into named booleans so the names document the business rule:
isAdmin := user.Role == RoleAdmin
isOwner := resource.OwnerID == user.ID
if isAdmin || isOwner || permissions.Has(PermOverride) {
allow()
}> Read [references/control-flow.md](references/control-flow.md) for tagless switch, guard clauses, and labelled break/continue.
Use `:=` for non-zero initializers, `var` when the zero value is the start.
var count int // start at 0 name := "default" // non-zero var buf bytes.Buffer // zero value is ready to use
A nil map panics on write; a nil slice JSON-encodes to `null` (a UX surprise for API consumers).
users := []User{} // explicit empty
m := map[string]int{} // explicit empty
users = make([]User, 0, len(ids)) // preallocate when size is known
m = make(map[string]int, len(items)) // preallocate map bucketsDo not speculatively preallocate large capacities — `make([]T, 0, 1000)` wastes memory when the common case is 10.
srv := &http.Server{
Addr: ":8080",
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}Positional fields break the moment the type adds or reorders a field.
| Anti-pattern | Why it hurts | Do this instead | |---|---|---| | Deeply nested `if` chains | Happy path scrolls off-screen | Invert, return early | | `if ok { return a } else { return b }` | `else` is dead weight | Drop the `else` | | `if x == A else if x == B else if x == C` | Reader has to verify all comparisons share `x` | `switch x { ... }` | | Positional struct literal | Breaks silently on field reorder | Named fields | | Nil map write | Runtime panic | `make(...)` or `map literal` | | `*string`, `*int` parameter to "save copy" | Adds indirection, no real saving | Pass value | | Long parameter lists | Hard to call, hard to extend | Options struct or `WithXxx` opts |
26 production-grade Go skills for Claude Code, Gemini CLI, and opencode. Battle-tested patterns from the Go community — codified as triggerable AI skills.
Repo: muratmirgun/gophers
Use when scaffolding or refactoring a Go service into a framework-agnostic clean (hexagonal) architecture: Domain, Usecase, Repository, Delivery layers, inward…
Invoke this skill to systematically review a Go change against community style standards before merging. Walks the diff topic by topic — formatting, errors,…
Use when writing or reviewing concurrent Go code — goroutines, channels, select, mutexes, atomics, errgroup, singleflight, worker pools, or fan-out/fan-in…
Use when designing, propagating, or debugging context.Context flow in Go — first-parameter placement, deadlines and cancellation, request-scoped values,…
Use when writing conditionals, loops, switches, type switches, or blank-identifier patterns in Go. Covers if-with-initialization, guard clauses, early returns,…
Use when choosing or operating on Go slices, maps, arrays, strings, or container/* types — including slice internals, capacity growth, preallocation, map…