Продвижение полей
Продвижение полей (field promotion) в Go позволяет обращаться к полям вложенной анонимной структуры напрямую, как если бы они были полями родительской структуры. Это работает только для анонимных полей (полей без имени), тип которых является структурой. При таком подходе поля вложенной структуры "поднимаются" на уровень внешней структуры и становятся доступными через точечную нотацию без указания имени вложенной структуры.
Синтаксис
Для использования продвижения полей необходимо объявить анонимное поле в структуре:
type Outer struct {
Inner // анонимное поле типа структуры
}
Теперь к полям структуры Inner можно обращаться напрямую
через экземпляр Outer:
outer := Outer{}
outer.FieldName = "value" // доступ к полю Inner
Пример
Рассмотрим простой пример продвижения полей. Создадим структуру
Address с полями City и Street, и структуру
Person с анонимным полем Address:
package main
import "fmt"
type Address struct {
City string
Street string
}
type Person struct {
Name string
Address // анонимное поле
}
func main() {
p := Person{
Name: "John",
Address: Address{
City: "New York",
Street: "5th Avenue",
},
}
fmt.Println(p.City) // прямой доступ к полю City
fmt.Println(p.Street) // прямой доступ к полю Street
}
Результат выполнения кода:
"New York"
"5th Avenue"
Как видите, поля City и Street доступны напрямую
через экземпляр Person, без необходимости указывать
p.Address.City.
Пример
При продвижении полей сохраняется возможность доступа к полям и через имя вложенной структуры. Это особенно полезно, если возникает конфликт имен:
package main
import "fmt"
type Contact struct {
Phone string
Email string
}
type User struct {
Name string
Contact
Email string // поле с таким же именем, как в Contact
}
func main() {
u := User{
Name: "Alice",
Contact: Contact{
Phone: "123-456",
Email: "alice@example.com",
},
Email: "alice@work.com",
}
// обращение к полю Email внешней структуры
fmt.Println(u.Email)
// обращение к полю Email вложенной структуры
fmt.Println(u.Contact.Email)
}
Результат выполнения кода:
"alice@work.com"
"alice@example.com"
В этом примере поле Email структуры User "затеняет"
поле Email из вложенной структуры Contact. При этом
доступ к полю вложенной структуры все равно возможен через ее имя.
Пример
Продвижение полей работает и для указателей на структуры. Рассмотрим пример с вложенным указателем:
package main
import "fmt"
type Config struct {
Host string
Port int
}
type Server struct {
Name string
*Config // указатель на структуру
}
func main() {
cfg := &Config{
Host: "localhost",
Port: 8080,
}
s := Server{
Name: "MainServer",
Config: cfg,
}
// прямой доступ к полям через указатель
fmt.Println(s.Host)
fmt.Println(s.Port)
}
Результат выполнения кода:
"localhost"
8080
При использовании указателя на структуру в качестве анонимного поля
продвижение работает аналогичным образом. Если указатель равен
nil, то при обращении к продвинутым полям произойдет паника,
поэтому нужно быть внимательным.
Смотрите также
-
концепцию
встраивания структур,
на котором основано продвижение полей -
механизм
продвижения методов,
который работает аналогично продвижению полей -
объявление
анонимных полей,
которые используются для продвижения -
доступ к
полям структуры,
включая именованные и анонимные поля