Go

What happens when two embedded types provide the same field or method name?

Question 89HardGo 1.22 to 1.25

Selector resolution uses depth. The name at the shallowest depth wins and shadows any deeper ones. If two or more names exist at the same shallowest depth, the selector is ambiguous. Ambiguity is a compile error only when you actually use the selector, and the ambiguous method is silently dropped from the outer type's method set.

type Reader struct{}
func (Reader) Close() error { return nil }

type Writer struct{}
func (Writer) Close() error { return nil }

type RW struct {
    Reader
    Writer
}

func main() {
    var rw RW
    // rw.Close()           // compile error: ambiguous selector rw.Close
    rw.Reader.Close()       // OK: explicit

    // var _ io.Closer = rw // compile error: RW does not implement io.Closer
    //                         (missing method Close) -- the ambiguity removes it
}

// Resolve by declaring the method at depth 0:
func (rw RW) Close() error {
    return errors.Join(rw.Reader.Close(), rw.Writer.Close())
}

A related trap is accidental shadowing. Embedding a type with a method named String or Error (for example, embedding time.Time or an error type) promotes that method and silently changes how fmt prints your outer struct.

More on Interfaces, Methods & Embedding

All 35 Interfaces, Methods & Embedding questions