Ответ
В Go нет классического наследования, как в языках вроде Java или C++. Вместо этого Go использует композицию через встраивание (embedding).
Встраивание для переиспользования кода
Вы можете встроить одну структуру в другую, и поля и методы встроенной структуры становятся доступными напрямую у внешней структуры. Это обеспечивает переиспользование кода, но не является наследованием.
Пример:
// "Базовый" тип
type Animal struct {
Name string
}
func (a *Animal) Speak() {
fmt.Printf("%s издает звукn", a.Name)
}
// "Производный" тип
type Dog struct {
Animal // Встраивание Animal в Dog
Breed string
}
// У Dog есть свой собственный метод
func (d *Dog) Bark() {
fmt.Printf("%s лает!n", d.Name)
}
func main() {
d := Dog{
Animal: Animal{Name: "Рекс"},
Breed: "Овчарка",
}
d.Speak() // Вызов метода из встроенной структуры Animal
d.Bark() // Вызов собственного метода Dog
}
Важное замечание: Если у структуры Dog будет свой метод Speak(), он не переопределит, а затенит метод из Animal. Метод Animal все еще можно будет вызвать явно: d.Animal.Speak().
Интерфейсы для полиморфизма
Полиморфизм в Go достигается с помощью интерфейсов. Интерфейс определяет набор методов. Любой тип, который реализует все методы интерфейса, неявно удовлетворяет этому интерфейсу.
// Интерфейс, описывающий поведение
type Speaker interface {
Speak()
}
// Функция, работающая с любым типом, который удовлетворяет интерфейсу Speaker
func MakeSound(s Speaker) {
s.Speak()
}
func main() {
dog := &Dog{Animal: Animal{Name: "Рекс"}}
// cat := &Cat{...} // Предположим, у Cat тоже есть метод Speak()
MakeSound(dog) // Работает, т.к. *Dog реализует Speak()
// MakeSound(cat) // Тоже будет работать
}
Итог: Go сознательно отказывается от наследования в пользу более гибкого и ясного подхода: композиция > наследование.
Ответ 18+ 🔞
Ну, слушай, тут такая история с Го, как с этим самым наследованием. Всё не как у нормальных людей, блядь! В Java или C++ — там всё понятно, отцов-классов натыкал и поехал. А тут, сука, принципиально иначе.
Вместо наследования у них, блядь, встраивание (embedding). Это как если бы ты не рожал наследника, а просто взял и засунул одного чувака в карман к другому. И теперь второй чувак может доставать из кармана первого его штуки и пользоваться, как своими. Ну, типа композиция, только на максималках.
Смотри, как это выглядит:
// Это типа наш "родитель", но не совсем
type Animal struct {
Name string
}
func (a *Animal) Speak() {
fmt.Printf("%s издает звукn", a.Name)
}
// А это наш "потомок", который просто засунул Animal себе внутрь
type Dog struct {
Animal // Вот это самое встраивание! Animal теперь в кармане у Dog
Breed string
}
// И у Dog свой личный метод есть
func (d *Dog) Bark() {
fmt.Printf("%s лает!n", d.Name) // Name-то он из кармана Animal достал!
}
func main() {
d := Dog{
Animal: Animal{Name: "Рекс"},
Breed: "Овчарка",
}
d.Speak() // И охуеть, работает! Метод Speak как будто свой.
d.Bark() // И свой метод тоже работает.
}
Но вот тут, блядь, важный момент, в рот меня чих-пых! Если ты в Dog напишешь свой метод Speak(), то он не переопределит старый, а просто затенит его. Старый-то метод всё ещё живёт в кармане, и к нему можно достучаться по полному адресу: d.Animal.Speak(). Никакой магии, всё честно.
А как же полиморфизм, ёпта?
А вот для этого у них отдельная, блядь, песня — интерфейсы. Это вообще гениальная хуйня. Ты описываешь набор действий (методов), и любой тип, который умеет эти действия делать, автоматически подходит под описание. Никаких explicit implements, нихуя!
// Говорим: "Всё, что умеет Speak() — это Speaker"
type Speaker interface {
Speak()
}
// И вот эта функция готова работать с кем угодно, кто Speaker
func MakeSound(s Speaker) {
s.Speak()
}
func main() {
dog := &Dog{Animal: Animal{Name: "Рекс"}}
// cat := &Cat{...} // Допустим, и кошка умеет Speak()
MakeSound(dog) // Всё заебись, *Dog умеет Speak(), значит он Speaker
// MakeSound(cat) // И кошка прокатит!
}
Короче, суть в чём: Го специально не даёт тебе классического наследования, чтобы ты не выстраивал эти ёбанные башни из слоновой кости в 10 этажей. Вместо этого — бери и компонуй из готовых кусков, как из лего. Композиция > наследования, вот их девиз. Сначала мозг ломает, а потом понимаешь — а оно и к лучшему, блядь.