go-code-review
Use when reviewing Go code or checking code against community style standards. Also use proactively before submitting a Go PR or…
Use when deciding whether to use Go generics, writing generic functions or types, choosing constraints, or picking between type aliases and type definitions. Also use when a user is writing a utility function that could work with multiple types, even if they don't mention
$ npx -y skills add cxuu/golang-skills --skill go-generics --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/go-genericsContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when deciding whether to use Go generics, writing generic functions or types, choosing constraints, or picking between type aliases and type definitions. Also use when a user is writing a utility function that could work with multiple types, even if they don't mention
name: go-generics description: Use when deciding whether to use Go generics, writing generic functions or types, choosing constraints, or picking between type aliases and type definitions. Also use when a user is writing a utility function that could work with multiple types, even if they don't mention generics explicitly. Does not cover interface design without generics (see go-interfaces).
> Compatibility: Generics require Go 1.18+.
Start with concrete types. Generalize only when a second type appears.
> "Write code, don't design types." — Robert Griesemer and Ian Lance Taylor
Do multiple types share identical logic? ├─ No → Use concrete types ├─ Yes → Do they share a useful interface? │ ├─ Yes → Use an interface │ └─ No → Use generics
**Bad:**
// Premature generics: only ever called with int
func Sum[T constraints.Integer | constraints.Float](vals []T) T {
var total T
for _, v := range vals {
total += v
}
return total
}**Good:**
func SumInts(vals []int) int {
var total int
for _, v := range vals {
total += v
}
return total
}---
| Name | Typical Use | |------|-------------| | `T` | General type parameter | | `K` | Map key type | | `V` | Map value type | | `E` | Element/item type |
For complex constraints, a short descriptive name is acceptable:
func Marshal[Opts encoding.MarshalOptions](v any, opts Opts) ([]byte, error)
---
Type aliases (`type Old = new.Name`) are rare — use only for package migration or gradual API refactoring.
---
Combine constraints with `~` (underlying type) and `|` (union):
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~float32 | ~float64
}
func Sum[T Numeric](vals []T) T {
var total T
for _, v := range vals {
total += v
}
return total
}Use the `constraints` package or `cmp` package (Go 1.21+) for standard constraints like `cmp.Ordered` instead of writing your own.
---
// Bad: generic wrapper adds complexity without value
type Set[T comparable] struct {
m map[T]struct{}
}
// Better: use map[T]struct{} directly when the usage is simple
seen := map[string]struct{}{}Generics justify their complexity when they eliminate duplication across **multiple call sites**. A single-use generic is just indirection.
// Bad: T is only used to satisfy an interface — just use the interface
func Process[T io.Reader](r T) error { ... }
// Good: accept the interface directly
func Process(r io.Reader) error { ... }// Bad: constraint is more restrictive than needed
func Contains[T interface{ ~int | ~string }](slice []T, target T) bool { ... }
// Good: comparable is sufficient
func Contains[T comparable](slice []T, target T) bool { ... }---
| Topic | Guidance | |-------|----------| | When to use generics | Only when multiple types share identical logic and interfaces don't suffice | | Starting point | Write concrete code first; generalize later | | Naming | Single uppercase letter (`T`, `K`, `V`, `E`) | | Type aliases | Same type, alternate name; use only for migration | | Constraint composition | Use `~` for underlying types, `|` for unions; prefer `cmp.Ordered` over custom | | Common pitfall | Don't genericize single-use code or when interfaces suffice |
---
AI Agent Skills for writing idiomatic, production-quality Go code. 20 modular skills teach AI coding assistants Go best practices derived from: Google Go Style Guide Effective Go Uber Go Style Guide Go Wiki CodeReviewComments Skills are tuned following
Use when reviewing Go code or checking code against community style standards. Also use proactively before submitting a Go PR or…
Use when writing concurrent Go code — goroutines, channels, mutexes, or thread-safety guarantees. Also use when parallelizing…
Use when working with context.Context in Go — placement in signatures, propagating cancellation and deadlines, and storing values…
Use when writing conditionals, loops, or switch statements in Go — including if with initialization, early returns, for loop…
Use when working with Go slices, maps, or arrays — choosing between new and make, using append, declaring empty slices (nil vs…
Use when declaring or initializing Go variables, constants, structs, or maps — including var vs :=, reducing scope with if-init,…