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
PersoninStudent,Studentgains access toPerson’s fields and methods. - Overriding: When
Studentdefines its ownAgefield orGrowUpmethod, it shadows the embedded ones. To access the embedded version, uses.Person.Ageors.Person.GrowUp(). - Best Practices: Overriding should be used carefully to avoid confusion. Prefer composition and interfaces for polymorphism in Go.