Go

Is struct embedding inheritance? How does method promotion work?

Question 86MediumGo 1.22 to 1.25

No. Embedding is composition with automatic delegation. An embedded field is an ordinary field named after its type, and the compiler promotes its fields and methods so they can be reached through the outer struct. A promoted method call is rewritten to a call on the inner value: outer.Log() becomes outer.Logger.Log(), and the receiver is still the inner value.

type Logger struct{ prefix string }
func (l *Logger) Log(msg string) { fmt.Println(l.prefix + msg) }

type Server struct {
    *Logger          // embedded; field name is "Logger"
    addr string
}

s := Server{Logger: &Logger{"[srv] "}, addr: ":8080"}
s.Log("started")        // promoted: s.Logger.Log("started")

type Loggable interface{ Log(string) }
var _ Loggable = s      // Server satisfies Loggable through promotion

// var l *Logger = &s   // compile error: no subtype relation

Embedding is not inheritance for several reasons:

  • A Server is not a Logger. You cannot pass it where a *Logger is expected.
  • There is no virtual dispatch. The inner type's methods never call back into the outer type's methods.
  • There is no super. You call s.Logger.Log explicitly.

The outer type does satisfy interfaces through promoted methods, which gives you polymorphism without subtyping.

More on Interfaces, Methods & Embedding

All 35 Interfaces, Methods & Embedding questions