Embedding promotes an embedded type’s fields and methods through the containing type. The convenience can accidentally expose implementation details, especially when embedding a mutex. section 2.10
Accidentally exporting a mutex
type InMem struct { sync.Mutex m map[string]int } func (i *InMem) Get(key string) (int, bool) { i.Lock() v, ok := i.m[key] i.Unlock() return v, ok } Because Lock and Unlock are promoted, clients can call inmem.New().Lock(). That exposes synchronization the type should normally encapsulate. section 2.10
Choose embedding according to the interface the containing type should expose:
- Use an unexported named field when the embedded behavior is implementation detail: mu sync.Mutex. section 2.10
- Embed when promotion intentionally supplies the containing type’s public behavior, such as Logger embedding io.WriteCloser and satisfying its interface. section 2.10
type Foo struct {
Bar #1
}
type Bar struct {
Baz int
}
Inspect how an embedded Bar makes Baz directly accessible through Foo, as in foo.Baz = 42. section 2.10
