compare Embedding Basics with an alternative
Fast recall
Quick revision
Core answer
Practical understanding of Embedding Basics.
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
Interface-in-struct embedding is the delegation pattern:
type LogReader struct {
io.Reader // embedded INTERFACE
prefix string
}
func (l LogReader) Read(p []byte) (int, error) {
n, err := l.Reader.Read(p) // or: rely on promotion below
// wrap/add behavior...
return n, err
}Two effects, both structural:
- 1
The struct SATISFIES the interface — io.Reader's method set (Read) counts as part of LogReader's method set via promotion. The compiler verifies it exactly as if you'd declared a Read method: var _ io.Reader = LogReader{}.
- 2
The promoted method FORWARDS to the field's value: l.Read(p) calls the io.Reader stored in l — whatever concrete reader was assigned at construction. The struct delegates by default.
The pattern this composes into — selective overriding:
func (l LogReader) Read(p []byte) (int, error) {
// custom Read — the OVERRIDDEN method
// l.Reader.Read still available for the forward
}Methods you don't redeclare forward automatically; methods you do redeclare shadow the promotion. One mechanism, exactly the decorator pattern: embed the interface, override what you wrap, inherit the forwarding of everything else.
The standard library's exhibits: bufio.Reader (embeds io.Reader — every bufio method that ISN'T Read is declared, and the embedded reader is the forward target), sort.Reverse (embeds sort.Interface, overrides ONLY Less — the three-line decorator), and the middleware pattern every Go web framework uses: handler struct { next http.Handler } IS this pattern with a different field spelling — embedding http.Handler promotes ServeHTTP, and overriding it IS middleware.
Why interface embedding rather than a named field: the named field gives NO satisfaction and NO promotion (must hand-write each forwarding method); the embedded interface gives both — the compiler writes the delegation for every method you don't override. That's the entire difference between a five-method forwarding boilerplate and one embedded line.
compare Embedding Basics with an alternative
Direct Answer
Embedding io.Reader in a struct promotes the interface's METHODS: the struct satisfies io.Reader, and calls forward to the concrete value stored in the field. Delegation with compile-time checking — the wrapper idiom.
Deep Dive & Architecture
The forwarding wrapper, one layer down: the promoted Read on the struct is a compiler-generated method whose body is 'call l.Reader.Read' — a load of the embedded interface field (two words: itable + data) followed by the itable-dispatched call. The struct satisfies io.Reader without containing any Read code — satisfaction is the generated wrapper.
That indirection is what makes the decorator sound: your own Read shadows the promotion — your method runs; calling l.Reader.Read inside it reaches the ORIGINAL behavior. Every non-overridden method forwards the same way, so a wrapper embedding an interface and overriding one method is automatically correct for the rest — the compiler maintains the delegation, not hand-written forwarding methods.
The nil-embedded-interface edge: a zero wrapper has a nil interface field; promoted calls through it panic (nil interface method call). Constructors must set the field — the same mandatory-init pattern as pointer embedding, same cure.
What embedding an interface CANNOT do that concrete embedding can: promote FIELDS (interfaces have none) or grant the struct the concrete type's OTHER interfaces (promotion composes from the embedded type's method set — the interface's methods only). The two forms are complementary: concrete-in-struct for state+behavior, interface-in-struct for pure delegation; wrappers needing both embed both.
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 Embedding Basics, and when would you use it?
- When would you use Embedding Basics in a real project?
- What is a common mistake when using Embedding Basics?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.