Nil vs empty slices
Choose `nil` versus empty slices deliberately at API boundaries because callers and encoders can observe the difference.
Canonical guidance
- treat
niland empty slices as different only when an API contract or encoder cares - return whichever value best matches the boundary contract
- be consistent within one API surface
Use when
- JSON or database boundaries
- helper APIs that return collections
- compatibility-sensitive responses
Avoid
- converting every
nilslice to empty by reflex - assuming callers cannot observe the difference
- mixing conventions across similar functions
Preferred pattern
func filter(xs []int) []int {
var out []int
for _, x := range xs {
if x%2 == 0 {
out = append(out, x)
}
}
return out
}
Anti-pattern
- patching slice emptiness repeatedly throughout the codebase instead of deciding at the boundary that needs it
Explanation: This anti-pattern is tempting because empty slices feel tidier, but unnecessary normalization adds noise and hides which boundary actually cares.
Why
- most internal code can treat both as empty, but external contracts sometimes cannot
Related pages
Sources
- Go Code Review Comments - Go Team
- Being confused about nil vs. empty slice (#22) - Teiva Harsanyi