Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Promoted methods in Go are methods belonging to an embedded (anonymous) field within a struct that are automatically exposed and accessible via the enclosing struct. Through struct embedding, the Go compiler implicitly forwards method calls from the outer struct to the inner embedded type, integrating the embedded type’s methods into the method sets of the enclosing struct or its pointer type, depending on receiver rules.

Mechanics of Promotion

When a type is declared as an anonymous field inside a struct, its methods are promoted to the method set of the enclosing struct or a pointer to the enclosing struct.
type Base struct {
    value int
}

func (b *Base) Increment() {
    b.value++
}

type Container struct {
    Base // Embedded anonymous field
}
In the example above, Container embeds Base as a value. Because Increment has a pointer receiver (*Base), it is promoted to the method set of *Container, not Container. However, Go provides syntactic sugar for method calls. If a Container instance is addressable (such as a local variable), Go implicitly takes its address to invoke the promoted pointer method:
c := Container{}
c.Increment() // Valid: c is addressable. Compiler translates to (&c).Base.Increment()

// Container{}.Increment() // Compile-time error: Container{} is an unaddressable value

Method Sets and Pointer Receivers

The exact method set promotion rules strictly adhere to Go’s specifications regarding value and pointer receivers. The resulting method sets depend on whether the embedded field is a value (T) or a pointer (*T):
  1. Embedding a Value Type (T):
    • Methods with a value receiver ((t T)) are promoted to the method sets of both Container and *Container.
    • Methods with a pointer receiver ((t *T)) are promoted only to the method set of *Container.
  2. Embedding a Pointer Type (*T):
    • Both value receiver ((t T)) and pointer receiver ((t *T)) methods are promoted to the method sets of both Container and *Container.
type Inner struct{}
func (i Inner) ValueMethod() {}
func (i *Inner) PointerMethod() {}

type OuterValue struct {
    Inner
}

type OuterPointer struct {
    *Inner
}

// Resulting Method Sets:
// OuterValue has: ValueMethod
// *OuterValue has: ValueMethod, PointerMethod
// OuterPointer has: ValueMethod, PointerMethod
// *OuterPointer has: ValueMethod, PointerMethod

Shadowing

If the enclosing struct defines a method with the exact same name as a promoted method, the enclosing struct’s method shadows the embedded type’s method. The embedded method is not overwritten; it simply loses its promoted status and must be accessed via explicit field traversal.
func (c *Container) Increment() {
    // Shadows Base.Increment()
    c.Base.Increment() // Explicit traversal to invoke the embedded method
}

Ambiguity and Collisions

If a struct embeds multiple anonymous fields that possess methods with identical names at the same depth, the compiler does not promote either method to the top level. Attempting to call the method directly on the enclosing struct results in a compile-time error due to an ambiguous selector.
type A struct{}
func (A) Process() {}

type B struct{}
func (B) Process() {}

type MultiContainer struct {
    A
    B
}

// mc := MultiContainer{}
// mc.Process() // Compile-time error: ambiguous selector mc.Process
// mc.A.Process() // Valid: explicit traversal resolves ambiguity
To resolve the collision at the promoted level, the enclosing struct must explicitly declare the method, thereby shadowing the embedded methods and providing a clear resolution path.

Interface Satisfaction

Because promoted methods become part of the enclosing struct’s (or its pointer’s) method set, the enclosing type automatically satisfies any interfaces implemented by the embedded type, provided the method set requirements are met.
type Incrementor interface {
    Increment()
}

// *Container implicitly satisfies Incrementor because Base.Increment 
// is promoted to the method set of *Container.
var _ Incrementor = (*Container)(nil)
Master Go with Deep Grasping Methodology!Learn More