Interfaces · 3 MIN READ
Embedding is not inheritance
Predict which method runs when an embedded type has one too.
Writing a type inside a struct without a field name embeds it, and its methods are promoted to the outer type. It looks like inheritance and is not: there is no virtual dispatch and no super. The outer type gets a field it can reach through, and the promoted methods still run against that inner value.
The consequence people trip on: a method the outer type declares shadows the promoted one for outside callers, but a promoted method calling a sibling still calls the inner one. Go resolves this at compile time by name, not at run time by receiver.
SEE THE IDEA
Promotion makes fields and methods easier to reach
- 01
Embedded field
gotype Outer struct { Inner }Outer contains an Inner value
- 02
Promotion
goouter.Run()A convenient path to Inner.Run
- 03
Explicit path
goouter.Inner.Run()The contained value is still there
Embedding is composition with promoted selectors.
In practice
Use embedding to expose a contained type deliberately, not to inherit an identity. The embedded value remains a field with its own receiver and state. A field or method on the outer type can hide a promoted selector; ambiguous promoted names must be reached through the explicit field path.
Watch out
Outer is not assignable to Inner just because Inner is embedded in it. Promoted methods can nevertheless satisfy interfaces.
Read and predict
package main
import "fmt"
type Base struct{ Name string }
func (b Base) Describe() string { return "base " + b.Name }
func (b Base) Greet() string { return "hello from " + b.Describe() }
type Loud struct{ Base }
func (l Loud) Describe() string { return "LOUD " + l.Name }
func main() {
l := Loud{Base{Name: "ada"}}
fmt.Println(l.Describe())
fmt.Println(l.Greet())
}What does this print? Look carefully at the second line.
Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.
Progress stays in this browser. No account needed.