a common mistake when using Embedding Basics
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
Pointer embedding is legal and common:
type App struct {
*User // embedded pointer
Name string
}
app := &App{User: &User{Name: "Al", Age: 30}, Name: "app"}
fmt.Println(app.Name2(), app.Greet()) // promotion through the pointerPromotion is unchanged: fields (app.UserName via app.User.Name promoted to app.Name — through the pointer, auto-dereferenced like any pointer field access) and methods (app.Greet() → the embedded *User's method set, which per the superset rule includes User's value-receiver methods too).
What changes:
- 1
The embedded field is a pointer — nil until assigned. A zero App has app.User == nil — and promoted calls through it panic on the nil dereference. Zero-value usability is lost unless the methods are nil-safe; constructors become mandatory in practice.
- 2
Sharing: the pointee lives outside the App. Two Apps embedding the same *User share it — writes through one are visible through the other. With value embedding, each Admin has its own User copy.
- 3
Initialization: the literal must supply a *User — usually constructed inline (App{User: &User{...}}). The extra & is the visible sign of the indirection.
Where the shape earns its keep: shared-state composition (several handlers embedding a *Config — one config, live updates shared), and template patterns where the embedded pointer is assigned LATE (a framework sets it after construction — the struct is a shell until then). The standard library's sync package exhibits the value-embedding side (Mutex by value), while dependency-injection codebases lean on pointer embedding for shared services — both idioms, distinguished by who owns the lifetime.
a common mistake when using Embedding Basics
Direct Answer
Yes — type App struct { *User }. Promotion works the same for fields and methods (through the pointer). Differences: the embedded field is a POINTER (nil until set), method calls auto-deref through it, and the inner struct is SHARED — mutations through the embedder reach the original.
Deep Dive & Architecture
The pointer-embed mechanics mirror pointer receivers: the promoted field access app.Name (through the embedded *User) compiles to an auto-dereference — (*app.User).Name — one indirection per access, same as any pointer field. The promoted method call app.Greet() routes through the *User's method set — which, by the superset rule, includes User's value-receiver methods too: everything a User can do, the pointer form can do.
The nil-embedded-pointer trap deserves the same prominence the typed-nil interface gets: a zero App has app.User == nil, and ANY promoted access panics on the nil dereference. Unlike the value-embed (zero Admin has a zero User — fields readable, methods callable), the pointer-embed's zero value is a landmine — which is why pointer-embedding types almost always ship with constructors that set the field. The pattern to recognize in review: type with a pointer-embed and NO NewX is asking for a nil-deref bug report.
The sharing semantics, mechanized: the embedded pointer field is one word in the struct — the pointee lives elsewhere. Copy the struct (assignment, value receiver): the pointer copies — both copies share the pointee. Two Apps embedding the same *User see each other's writes. Contrast value-embedding: each copy carries its own deep User. The choice is the classic value-vs-reference decision, moved to the field level — and the same rules (isolate vs share, immutable vs live) apply.
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?
- How would you compare Embedding Basics with an alternative?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.