a common mistake when using Value Vs Pointer Receivers
Fast recall
Quick revision
Core answer
Practical understanding of Value Vs Pointer Receivers.
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 rule, then the consequences:
func (u User) Greet() string
func (u *User) Inc()
var g Greeter // interface { Greet() string }
var u User
var p *User = &u
g = u // works — Greet is in User's method set (value receiver)
g = p // works — *User's set is a SUPERSET
var inc Incrementer // interface { Inc() }
inc = u // COMPILE ERROR — Inc is not in User's method set
inc = p // works — Inc is in *User's method setThe asymmetry's direction matters: the POINTER can always stand in for the value (its method set includes everything the value's does) — but not the reverse. A pointer-heavy type (all methods on *User) satisfies its interfaces only at pointer type; storing values in interfaces fails at compile time with the method-set error.
The classic bug shape: a constructor returns User (value), methods are pointer receivers, users try to store in the interface — the compiler names the missing method. The fixes, by idiom: constructors of pointer-receiver types return *User (the standard library's pattern — NewBuffer() *Buffer); or the type moves its methods to value receivers (when mutation isn't needed); or the interface gets satisfied by a wrapper. The first fix is the convention because it makes the whole type's usage uniform — everything holds *User.
The storage consequence worth naming: interface values hold a copy of what you put in (u boxed into the interface is a snapshot — mutating the original u after doesn't affect the boxed copy; boxing p copies the POINTER — the pointee stays shared). Receiver kinds, method sets, and interface semantics are one system — the receiver choice at type-design time decides the interface story forever.
a common mistake when using Value Vs Pointer Receivers
Direct Answer
Rule: *T's method set includes value AND pointer receivers; T's includes only value receivers. So pointer-receiver methods make the type satisfy interfaces ONLY as the pointer.
Deep Dive & Architecture
The boxed-value mechanics explain the rule from the inside out. An interface value is two words: (type pointer, data pointer). When you assign u (a User) into an interface variable, the compiler stores User's type descriptor and a POINTER TO A COPY of u. When you assign p (a *User), it stores *User's descriptor and p itself.
Method call through the interface: the call reads the type descriptor's method table — for the boxed User, that table IS User's method set; for the boxed *User, it is the superset table. The rule is not a policy layered on top; it is literally which table the runtime can find in the box.
Now the why of the asymmetry: if a User value were allowed to satisfy an Inc() interface, the runtime would need to call a pointer-receiver method with only a pointer to the boxed COPY — a copy the method may mutate — and that mutation would land in the interface's internal copy, invisible to any variable you hold. That's the semantic hole the rule closes: value-in-interface + pointer method = mutating a secret copy. Go refuses at compile time rather than deciding the mutation's fate silently.
The constructor corollary that the ecosystem settled: types with pointer receivers have constructors returning pointers — NewBuffer() *Buffer, not NewBuffer() Buffer. The convention eliminates the failure mode at birth: everything the user holds is the pointer form; every interface the type satisfies is satisfied by everything the user holds. The compile error the rule produces is the teacher — a generation of Go developers learned method sets from exactly this error, and the convention makes sure the lesson arrives in design review, not production.
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 Value Vs Pointer Receivers, and when would you use it?
- When would you use Value Vs Pointer Receivers in a real project?
- How would you compare Value Vs Pointer Receivers with an alternative?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.