Ответ
В Go отсутствует классическое наследование, как в языках вроде Java или C++. Вместо этого Go продвигает принцип композиции над наследованием, основным инструментом для которой является встраивание (embedding).
Встраивание (Embedding)
Это механизм, позволяющий одной структуре "включить" в себя другую. Поля и методы встроенной структуры "поднимаются" на уровень внешней, что обеспечивает удобный доступ к ним.
import "fmt"
type Animal struct {
Name string
}
func (a Animal) Speak() {
fmt.Printf("%s издает звук животногоn", a.Name)
}
type Dog struct {
Animal // Встраивание структуры Animal
Breed string
}
func main() {
d := Dog{
Animal: Animal{Name: "Рекс"},
Breed: "Овчарка",
}
// Метод Speak() "поднялся" на уровень Dog
d.Speak() // Вывод: Рекс издает звук животного
// Поле Name также доступно напрямую
fmt.Println(d.Name) // Вывод: Рекс
}
Ключевые отличия от наследования
Отношение "is a" vs "has a": Наследование моделирует отношение "является" (Собака является Животным). Встраивание — это отношение "имеет" (Собака имеет свойства Животного). Это композиция.
Отсутствие иерархии типов:
Dog
не является подтипомAnimal
. Переменной типаAnimal
нельзя присвоить значение типаDog
. Для полиморфизма в Go используются интерфейсы.Нет переопределения (Overriding): Если у
Dog
будет свой методSpeak()
, он не переопределит, а скроет (shadow) метод изAnimal
. МетодAnimal
останется доступным через явное указание:d.Animal.Speak()
.Явный доступ: Всегда можно обратиться к полям и методам встроенной структуры напрямую через ее тип:
d.Animal.Name
.