Go

How does struct embedding affect method sets and name resolution?

Question 30HardGo 1.22 to 1.25

Embedding promotes the embedded type's fields and methods to the outer type. For a struct S:

  • If S embeds T: the method set of S gets T's value methods. The method set of *S gets both T's and *T's methods.
  • If S embeds *T: both S and *S get T's and *T's methods.
type Logger struct{}
func (l *Logger) Log(msg string) { fmt.Println(msg) }

type Service struct{ Logger }       // embeds the value type

type Loggable interface{ Log(string) }

var _ Loggable = &Service{}         // OK
// var _ Loggable = Service{}       // compile error: Log has a pointer receiver on Logger

type A struct{}
func (A) Hello() string { return "A" }
type B struct{}
func (B) Hello() string { return "B" }

type C struct{ A; B }
// C{}.Hello()                      // compile error: ambiguous selector
fmt.Println(C{}.A.Hello())          // OK: say which one explicitly

type D struct{ A }
func (D) Hello() string { return "D" } // the shallower method shadows A.Hello

Key points:

  • Embedding is composition, not inheritance. A promoted method's receiver is the inner value. It knows nothing about the outer type, so there is no virtual dispatch or "override" that the inner code can see.
  • A name at a shallower depth wins. The same name at the same depth is ambiguous, which is an error only if you actually use it.
  • Embedding a sync.Mutex in an exported type makes Lock and Unlock part of your public API. Use a named field instead.

More on Language Fundamentals & Types

All 39 Language Fundamentals & Types questions