debug a problem involving Method Sets
Fast recall
Quick revision
Core answer
Practical understanding of Method Sets.
Repeating a definition without saying when to use it.
Give one trade-off and say how you would test it.
Interview-ready guide
Interview answer
The receiver kind is the entire answer, and the executed proof is three lines:
func (u User) Rename(s string) { u.Name = s } // value: copy's name changes
func (u *User) RenamePtr(s string) { u.Name = s } // pointer: original changes
u := User{Name: "Al"}
u.Rename("Bo")
fmt.Println(u.Name) // "Al" — the value receiver's change is gone
p := &u
p.RenamePtr("Cy")
fmt.Println(u.Name) // "Cy" — the pointer receiver's change persistsThe mechanics: the value receiver's method body operates on a copy made at call time — every field write lands in the copy's storage, which evaporates at return. The pointer receiver's body dereferences to the caller's actual variable — writes land in the original.
The half-mutation trap (worth its own mention in any answer): the value receiver's copy is SHALLOW — a slice field's elements are shared with the original. u.Tags[0] = "x" through a VALUE receiver mutates the original's slice contents (same backing array) — while u.Tags = append(...) rebinds only the copy's header. So 'value receivers can't modify' needs its precise form: they can't modify the RECEIVER (the struct's own fields), but writes through the receiver's reference-typed fields DO escape. That escape is the #1 value-receiver bug in real code.
The interface consequence connects to method sets: a type whose mutating methods are pointer receivers can only satisfy interfaces AS THE POINTER — []Incrementer can't hold User values (Inc isn't in User's method set). The modification decision cascades: receiver kind → method set → interface satisfaction → what the type can be stored in.
debug a problem involving Method Sets
Direct Answer
Pointer receiver (u *User): modifications persist — the method holds the receiver's address. Value receiver (u User): modifications die with the copy — the original is untouched. The receiver kind IS the modification contract.
Deep Dive & Architecture
The compiler's view of the two receivers, because it explains every behavior:
Value: the call passes the struct's CONTENTS as the argument — same as any by-value parameter. The method's u is a fresh stack slot (or register-passed struct), constructed by copying the caller's value. Mutation is impossible BY CONSTRUCTION — the method has no reference to the original.
Pointer: the call passes ONE WORD — the address. The method's u is that address; every field access is u.Name compiling to (*u).Name — an indirection to the caller's storage. Mutation is possible BY CONSTRUCTION — the original is reachable.
The shallow-copy subtlety mechanically: the value receiver's copy duplicates each FIELD — a slice field's header (pointer, len, cap) is copied, so both the original and the copy hold pointers to the SAME backing array. Indexed writes go through the shared array (visible both ways); the copy's header rebinding (append, assignment) is private. This is why 'does the value receiver protect me?' has the answer 'structurally yes, referentially no' — the protection is exactly one layer deep.
Escape analysis interacts once more: a pointer receiver forces the method to hold the receiver's address — if the caller's value was a temporary that the compiler materialized for the call, it now needs a stable address (a real allocation, potentially heap). The ubiquitous 'methods on large structs should use pointer receivers' performance rule is really this: copy cost (value) versus indirection + possible allocation forcing (pointer). For immutable small structs — time.Time at 24 bytes — value receivers win on every axis; the standard library's receiver choices are a curated exhibit of the trade.
Common Mistakes & Pitfalls
Repeating a definition without saying when to use it.
Check your understanding
Answer these without looking back at the article.
- What is Method Sets, and when would you use it?
- When would you use Method Sets in a real project?
- How would you compare Method Sets with an alternative?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.