В Go embedding (встраивание) — это механизм, позволяющий "наследовать" поведение структуры путем встраивания одной структуры в другую без использования явного наследования, как, например, в OOP. Встраиваемая структура становится полями-встраиваемой (анонимными полями) новой структуры.
При этом все методы встраиваемой структуры становятся методами новой структуры, будто бы "наследуются".
Пример:
package main import "fmt" type Animal struct { Name string } func (a Animal) Speak() { fmt.Println("My name is", a.Name) } type Dog struct { Animal // embedding, анонимное поле Breed string } func main() { d := Dog{ Animal: Animal{Name: "Rex"}, Breed: "Shepherd", } d.Speak() // Наследованный метод! fmt.Println(d.Name) // Поле доступно напрямую }
Главная разница между embedding и обычным включением структуры как именованного поля:
"Если встраиваемая структура и внешняя содержат поля с одинаковыми именами, какое будет использоваться и как к ним обратиться?"
Многие считают, что будет использовано только "верхнее" поле, но это работает иначе:
Пример:
type Base struct { Name string } type Child struct { Base // embedding Name string // совпадающее поле } c := Child{Base: Base{Name: "Base"}, Name: "Child"} fmt.Println(c.Name) // Child fmt.Println(c.Base.Name) // Base
История
В проекте встраивали стандартную структуру для логгирования, а затем определили поле
Loggerв дочернем типе. В результате, вызовыd.Logger.Info()работали не как ожидалось, потому что доступ к встроенному полю "терялся" среди одноименных.
История
Разработчик пытался переопределить метод в дочерней структуре, но методов не "override-ятся" — просто появляется новый, и родительский по-прежнему доступен как
Child.Base.Method(). Это приводило к тому, что часть кода использовала "старую" версию метода, ожидая другую логику.
История
При сериализации JSON с вложенными структурами возникали неожиданности: поля "встраиваемой" структуры появлялись в корневом объекте. Из-за незнания, как embedding влияет на marshaling, структура сериализовалась некорректно, ломая обратную совместимость API.