Field and Method Overriding in Go

Go achieves inheritance-like behavior through embedding. An outer struct can automatically access the fields and methods of the embedded struct.

When using embedding, both fields and methods can be overridden. If not overridden, they can be accessed directly from the outer struct. If overridden, you need to explicitly reference the inner struct for fields or methods.

Note: Fields here are similar to instance variables in other languages.

Field Overriding

package main

import "fmt"

// Person struct
type Person struct {
    Age  int
    Name string
}

// Field overriding example.
// If you want to reference the inner field, you need to explicitly specify it.
// Student has the same field `Age` as Person
type Student struct {
    Person
    Age int
}

func main() {
    p := Person{12, "lily"}
    fmt.Println(p)

    s := Student{Person{12, "lily"}, 19}
    fmt.Println(s)
    fmt.Println(s.Person.Age) // Access inner Age
    fmt.Println(s.Age)        // Access outer Age
    fmt.Println(s.Name)       // Access Name (not overridden)
    fmt.Println(s.Person.Name)
}

Output:

{12 lily}
{{12 lily} 19}
12
19
lily
lily

Method Overriding

// Method overriding example

package main

import "fmt"

type Person struct {
    age int
}

type Student struct {
    Person
}

func (p *Person) GrowUp() {
    p.age = p.age + 1
}

func (p *Student) GrowUp() {
    p.age = p.age + 3
}

func newPerson(age int) *Person {
    return &Person{age}
}

func main() {
    // person
    p := newPerson(12)
    fmt.Println(p.age)
    p.GrowUp()
    fmt.Println(p.age)

    // student
    s := &Student{Person{16}}
    fmt.Println(s.age)
    // Explicitly call inner method
    s.Person.GrowUp()
    fmt.Println(s.age)
    // Call the overridden method
    s.GrowUp()
    fmt.Println(s.age)
}

Output:

12
13

16
17
20

Explanation

  • Embedding: Go uses composition over inheritance. By embedding Person in Student, Student gains access to Person’s fields and methods.
  • Overriding: When Student defines its own Age field or GrowUp method, it shadows the embedded ones. To access the embedded version, use s.Person.Age or s.Person.GrowUp().
  • Best Practices: Overriding should be used carefully to avoid confusion. Prefer composition and interfaces for polymorphism in Go.

Resources