Receiver choice
Choose pointer or value receivers consistently based on mutation, size, and semantics.
Canonical guidance
- use pointer receivers when methods mutate state
- use pointer receivers for large structs or when copying is undesirable
- avoid mixing pointer and value receivers on the same type unless there is a strong reason
- value receivers fit small immutable value-like types
Use when
- designing methods for a new type
- reviewing API consistency
Avoid
- mixed receiver sets on ordinary structs
- value receivers on types that contain mutexes
- pointer receivers just by habit when value semantics are intended
Preferred pattern
type Counter struct {
n int
}
func (c *Counter) Inc() { c.n++ }
Anti-pattern
func (c Counter) Inc() { c.n++ }
Explanation: This anti-pattern is tempting when methods evolve one by one, but mixed receiver semantics create subtle copying and API-consistency issues.
Why
- receiver choice communicates semantics
- mixed choices create confusion around copying and mutation
Sources
- Effective Go - Go Team
- Go Code Review Comments - Go Team