Pointer receiver — the method receives *T, can modify the original value, avoids copying. Value receiver — the method receives T, works on a copy, cannot affect the original.
The choice affects mutability, performance, and interface satisfaction. If you define even one method with a pointer receiver, Go encourages (but doesn't enforce) making all methods on that type use pointer receivers for consistency.
1type Counter struct {2 n int3}45// Pointer receiver — modifies the original6func (c *Counter) Inc() {7 c.n++8}910// Value receiver — read-only11func (c Counter) Value() int {12 return c.n13}1415var c Counter16c.Inc()17c.Inc()18fmt.Println(c.Value()) // 2
Performance consideration: Value receivers copy the entire struct. For small structs (one or two fields) this is negligible. For large structs (embedded slices, maps, many fields), pointer receivers avoid the copy.
When to use:
Common mistakes:
nil receivers (they receive a copy of nil, which can still dereference fields if they are pointers).