Встраивание структур
Встраивание структур (struct embedding) в Go — это механизм композиции, позволяющий включить одну структуру в другую как анонимное поле. При встраивании все поля и методы встроенной структуры становятся доступными непосредственно через внешнюю структуру без явного указания имени поля. Это дает возможность переиспользовать функциональность и строить иерархии на основе композиции, а не наследования. Встраивание реализуется через объявление поля с типом структуры, но без имени.
Синтаксис
Встраивание структуры выполняется путем указания типа структуры в качестве поля без имени:
type Outer struct {
Inner // встроенная структура
Field string
}
В этом примере структура Outer включает в себя структуру
Inner через встраивание. Все поля и методы структуры
Inner становятся доступными непосредственно через
экземпляр Outer.
Пример
Давайте создадим структуру User с базовой информацией
о пользователе и встроим ее в структуру Admin:
package main
import "fmt"
type User struct {
Name string
Age int
}
type Admin struct {
User // встраивание User
IsActive bool
}
func main() {
admin := Admin{
User: User{
Name: "Alice",
Age: 30,
},
IsActive: true,
}
fmt.Println(admin.Name) // доступ к полю Name
fmt.Println(admin.Age) // доступ к полю Age
fmt.Println(admin.IsActive)
}
Результат выполнения кода:
"Alice"
30
true
Как видно из примера, поля Name и Age доступны
напрямую через admin, как если бы они были объявлены
в структуре Admin.
Пример
Рассмотрим пример с методами встроенной структуры.
Создадим структуру Logger с методом Log
и встроим ее в структуру Service:
package main
import "fmt"
type Logger struct {
Prefix string
}
func (l Logger) Log(msg string) {
fmt.Println(l.Prefix + ": " + msg)
}
type Service struct {
Logger // встраивание Logger
Name string
}
func main() {
svc := Service{
Logger: Logger{Prefix: "API"},
Name: "UserService",
}
svc.Log("Starting service") // вызов встроенного метода
}
Результат выполнения кода:
"API: Starting service"
Метод Log из встроенной структуры Logger
доступен напрямую через Service, что позволяет
расширять функциональность без явного делегирования.
Пример
При встраивании структур с одинаковыми именами полей может возникнуть конфликт. В таком случае доступ к полю осуществляется через явное указание встроенной структуры:
package main
import "fmt"
type Address struct {
City string
}
type Contact struct {
City string
}
type Person struct {
Address
Contact
Name string
}
func main() {
p := Person{
Address: Address{City: "Moscow"},
Contact: Contact{City: "Berlin"},
Name: "Bob",
}
fmt.Println(p.Address.City) // явный доступ к полю Address
fmt.Println(p.Contact.City) // явный доступ к полю Contact
}
Результат выполнения кода:
"Moscow"
"Berlin"
При наличии конфликта имен компилятор требует явного указания, к какому именно полю осуществляется доступ.
Смотрите также
-
механизм
анонимных полей,
которые являются основой для встраивания -
понятие
продвижения полей,
которое обеспечивает доступ к полям встроенных структур -
механизм
продвижения методов,
который работает аналогично продвижению полей -
общее описание
структур в Go,
с которых начинается изучение этого типа данных