有时你会看到在 Golang 中定义结构体时,有种写法是只定义类型而不定义字段名。下面将介绍这种被称为匿名字段的语法,以及它能够实现的作用。
匿名字段
在定义结构体的时候,如果一个字段没有声明名称而只声明了类型,那么这个字段就是一个匿名字段(anonymous fields)。该字段的名称和类型一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main
import ( "fmt" )
type User struct { name string }
type Service struct { User string int }
func main() { s := Service{ User: User{ name: "Jack", }, string: "foo", int: 1, } fmt.Printf("%s %s %d\n", s.User, s.string, s.int) }
|
https://play.golang.org/p/oDE7NxiTWWf
提升字段
同时匿名字段还有一个附带效果,就是提升(promotion)。如果在结构体中定义一个子结构体作为匿名字段,那么这个子结构体的字段(promoted fields)和方法(promoted methods)都会被提升到父结构体中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package main
import ( "fmt" )
type user struct { name string }
func (u *user) Greet() { fmt.Printf("Hello, I'm %s\n", u.name) }
type Service struct { name string user }
func main() { s := Service{ name: "test service", user: user{ name: "Jack", }, } fmt.Printf("%s %s\n", s.name, s.user.name) s.Greet() s.user.Greet() }
|
https://play.golang.org/p/zs_d4uknP8Z
需要注意,提升字段实际上是一个语法糖,被提升的方法中调用的属性还是子结构体的,并不能通过提升获取父结构体中的属性。