Embedding is not inheritance: what does this print, and which line does not compile?
type Base struct{}
func (Base) Name() string { return "base" }
func (b Base) Greet() string { return "hi " + b.Name() }
type Derived struct{ Base }
func (Derived) Name() string { return "derived" }
type A struct{}
type B struct{}
func (A) Hello() string { return "A" }
func (B) Hello() string { return "B" }
type C struct {
A
B
}
func main() {
d := Derived{}
fmt.Println(d.Name(), d.Greet(), d.Base.Name())
var c C
fmt.Println(c.A.Hello())
// fmt.Println(c.Hello()) // compile error: ambiguous selector c.Hello
type P struct{ *A }
var p P
fmt.Println(p.Hello()) // panics
}
It prints derived hi base base, then A, then panics with a nil pointer dereference.
d.Greet() is promoted from Base, and it runs with a Base receiver. Inside it, b.Name() is resolved statically to Base.Name. Go has no virtual dispatch through embedding, so the "override" in Derived is never called from Base's methods. If you need that, use an interface field or pass the behaviour in as a function.
When two embedded types at the same depth both provide Hello, neither is promoted. The struct still compiles, and the error appears only when someone writes c.Hello(). C also does not satisfy interface{ Hello() string }. A method declared on the outer type, or a field at a shallower depth, would win instead. This means adding a method to an embedded library type can silently break or change your code.
Embedding a pointer promotes its methods too. With a nil *A, the value-receiver Hello has to dereference the pointer to copy the receiver, so the call panics. Code-review angle: embedding a type such as sync.Mutex in an exported struct also exports Lock and Unlock as part of your API.
More on Tricky Output & Code-Review Puzzles
- Q511What does this counter print, and how do you prove the bug?
- Q512Deleting from a slice in place: what do both lines print?
- Q514Type switch puzzle: what does describe return for each input?
- Q515Package initialization order: what does this program print?