debug a problem involving Implicit Satisfaction
Fast recall
Quick revision
Core answer
Practical understanding of Implicit Satisfaction.
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 executed proof:
var g Greeter // nil interface
g == nil // true
var p *User // nil pointer
var g2 Greeter = p // box the typed nil
g2 == nil // false!Two states that look identical in casual reading. The interface value is (type, value) — two words. The nil interface has both zero. The typed-nil interface has the type word set (*User) and the value word nil — the interface KNOWS its type, and that makes it non-nil.
Why this is Go's most famous bug: a helper returns (nil, err) — but if the function's return type is an INTERFACE, the caller's err != nil check sees the typed nil and the 'error path' looks like success:
func loadUser() *User { return nil }
var g Greeter = loadUser()
g == nil // false — the trap sprungThe fix patterns: return concrete types from functions (the caller boxes — a nil *User compared as a pointer IS nil); or return the interface type and explicitly return nil (the literal — the nil interface); or use errors instead of nil returns for failure.
The comparison rule in one line: interface == nil compares BOTH words — type AND value must be nil. A typed nil has a non-nil type word, so the comparison fails.
debug a problem involving Implicit Satisfaction
Direct Answer
Nil interface: both words zero — == nil is true. Interface holding a nil *T: the type word is set — == nil is FALSE. The classic Go bug: returning a typed nil in an error path.
Deep Dive & Architecture
The two-word representation explains everything: interface values are (type-descriptor pointer, data pointer). The comparison g == nil compiles to 'both words are zero.' Boxing p (a nil *User) into Greeter writes the type word (*User's descriptor — non-zero) and the data word (the nil pointer, copied into the interface's storage). So the interface is 'a *User that happens to be nil' — a meaningful state, distinct from 'nothing.'
The method-call behavior through a typed nil: calling g.Greet() finds *User's Greet in the itable and passes the nil pointer as the receiver. If Greet is a pointer-receiver method that dereferences — panic. If it handles nil receivers — it works, a legitimate pattern: nil-receiver methods.
The standard library's own incidence — where typed nils are deliberate: a nil *bytes.Buffer, a nil map inside a struct field (methods on nil receivers work: append to nil slices, read from nil maps — the nil-tolerant method family). The bug shape is specifically the INTERFACE boundary: code that would have compared a concrete nil correctly compares a boxed typed nil incorrectly. The rule that prevents it: never return a typed nil where the caller will see an interface — return untyped nil or a concrete type.
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 Implicit Satisfaction, and when would you use it?
- When would you use Implicit Satisfaction in a real project?
- How would you compare Implicit Satisfaction with an alternative?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.