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 designing, propagating, or debugging context.Context flow in Go — first-parameter placement, deadlines and cancellation, request-scoped values, WithoutCancel for fire-and-forget work, and key-collision-safe value patterns. Apply proactively whenever a function takes
$ npx -y skills add muratmirgun/gophers --skill go-context --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/go-contextContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when designing, propagating, or debugging context.Context flow in Go — first-parameter placement, deadlines and cancellation, request-scoped values, WithoutCancel for fire-and-forget work, and key-collision-safe value patterns. Apply proactively whenever a function takes
name: go-context description: "Use when designing, propagating, or debugging context.Context flow in Go — first-parameter placement, deadlines and cancellation, request-scoped values, WithoutCancel for fire-and-forget work, and key-collision-safe value patterns. Apply proactively whenever a function takes ctx, spawns work, or accepts request-scoped data, even if the user has not asked about context." license: MIT compatibility: "Designed for Claude Code or similar AI coding agents. Requires Go 1.7+ (context in std lib). context.WithoutCancel needs Go 1.21+." allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*)
`context.Context` carries the cancellation, deadline, and request-scoped values for a single unit of work. Pass it explicitly through the entire call chain — never store it, never replace it with `Background()` mid-flight, never use it as a side-channel for ordinary parameters.
1. **`ctx` is the first parameter**, named `ctx context.Context`. No exceptions outside interface stubs imposed by external APIs. 2. **Propagate the caller's `ctx`** all the way down. Do not start a new tree with `context.Background()` inside a request path. 3. **Do not store `Context` in a struct**. Pass it to each method that needs it. 4. **Always `defer cancel()`** after `WithCancel`/`WithTimeout`/`WithDeadline`, unless ownership is explicitly transferred. 5. **Context values are for request-scoped metadata only** (request ID, auth principal, trace). Never for optional function parameters or config. 6. **Value keys must be unexported named types** to prevent cross-package collisions.
Pick the most explicit option that fits — context values are the last resort.
| Option | Use for | Why | |---|---|---| | Function parameter | Anything the function *needs* to do its job | Type-checked, visible at call site | | Method receiver | State that belongs to the type | Already in scope | | Package-level config | Process-wide, immutable | One owner, no hidden flow | | `context.Value` | Request-scoped metadata that crosses layers without being a function arg | Untyped — use sparingly |
> Read [references/values-and-keys.md](references/values-and-keys.md) for the unexported-key pattern, typed accessors, and OpenTelemetry/trace propagation.
| Situation | Use | |---|---| | `main`, `init`, top-level test | `context.Background()` | | Placeholder while plumbing is incomplete | `context.TODO()` | | Inside an HTTP handler | `r.Context()` | | Need manual cancellation | `context.WithCancel(parent)` | | Need a deadline / timeout | `context.WithTimeout(parent, d)` / `WithDeadline` | | Background work that must outlive the request (Go 1.21+) | `context.WithoutCancel(parent)` |
// Bad — breaks the chain, downstream cannot be cancelled
func (s *OrderService) Create(ctx context.Context, o Order) error {
return s.db.ExecContext(context.Background(), insertSQL, o.ID)
}
// Good — same ctx flows HTTP handler -> service -> DB -> external API
func (s *OrderService) Create(ctx context.Context, o Order) error {
return s.db.ExecContext(ctx, insertSQL, o.ID)
}ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel() // release resources even on the happy path
select {
case <-ctx.Done():
return ctx.Err()
case res := <-doAsync(ctx):
return res
}> Read [references/cancellation-and-deadlines.md](references/cancellation-and-deadlines.md) for `WithoutCancel`, `AfterFunc`, and long-running goroutine cancellation patterns.
// Bad — pollutes the standard signature
type MyCtx interface {
context.Context
UserID() string
}
// Good — keep the signature standard, extract via helper
func UserIDFrom(ctx context.Context) (string, bool) { /* ... */ }Most context mistakes are mechanical and a linter will catch them in CI before review:
Run `golangci-lint run --enable=contextcheck,noctx,staticcheck` in CI for any project that exposes `context.Context`.
| Anti-pattern | Why it hurts | Do this instead | |---|---|---| | `ctx context.Context` stored on a struct field | Lifetime becomes invisible; outlives the request | Pass `ctx` to each method | | `context.Background()` mid-call | Cancellation chain breaks; goroutines leak | Use the caller's `ctx` | | `ctx.Value("user-id")` with a string key | Cross-package collisions, no type safety | Unexported key type + typed getter | | Passing `nil` as a context | Panics on `Done()` / `Value()` | Use `context.TODO()` while plumbing | | `WithTimeout` without `defer cancel()` | Leaks the timer until parent finishes | `defer cancel()` on the next line | | Custom `MyContext` interface | Breaks every standard signature | Keep `context.Context`, extract with helpers |
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 Go code for clarity, formatting, control flow, variable declarations, switch usage, and function design. Covers the priority…
Use when writing or reviewing concurrent Go code — goroutines, channels, select, mutexes, atomics, errgroup, singleflight, worker pools, or fan-out/fan-in…
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…