go-genericslisted
Install: claude install-skill muratmirgun/gophers
# Go Generics
Generics are a powerful but easy-to-misuse feature. The Go answer is pragmatic: write concrete code first, then generalize only when you have a real second caller.
## Core Rules
1. **Write concrete first.** Reach for generics only when a second type actually needs the same logic.
2. **If an interface already models the behavior, use the interface.** Don't pile type parameters on top.
3. **Prefer standard constraints** (`comparable`, `cmp.Ordered`, `any`) over hand-rolled unions.
4. **Don't over-constrain.** `comparable` is usually enough; the narrower the constraint, the fewer callers benefit.
5. **Name type parameters with a single uppercase letter** (`T`, `K`, `V`, `E`) unless a longer name genuinely helps.
6. **Don't use generics for interface satisfaction.** `func F[T io.Reader](r T)` is just `func F(r io.Reader)`.
7. **Don't wrap stdlib containers** "for generic convenience" unless you eliminate real duplication.
## Decision Flow
```
Multiple types need the same logic?
├─ No → concrete type
├─ Yes → do they share a useful interface?
│ ├─ Yes → use the interface
│ └─ No → use generics
```
## When NOT to Use Generics
```go
// Premature: only ever called with int
func Sum[T constraints.Integer | constraints.Float](xs []T) T {
var t T
for _, x := range xs { t += x }
return t
}
// Better
func SumInts(xs []int) int {
var t int
for _, x := range xs { t += x }
return t
}
```
> "Write code, don't design types." — Grie