1)结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段、方法,都可以使用。
package main
import "fmt"
type A struct {
Name string
age int
}
func (a *A) SayName() {
fmt.Println("A say name", a.Name)
}
func (a *A) sayAge() {
fmt.Println("A say age", a.age)
}
type B struct {
sex string
A
}
func main() {
b := &B{
sex: "male",
A: A{
Name: "lucas",
age: 29,
},
}
b.SayName()
b.A.sayAge()
fmt.Println(b.Name)
fmt.Println(b.age)
}
2)匿名结构体字段访问可以简化,如图
对上面的代码小结
(1)当我们直接通过b 访问字段或方法时,其执行流程如下比如b.Name
(2)编译器会先看b对应的类型有没有Name,如果有,则直接调用B类型的Name字段
(3)如果没有就去看B中嵌入的匿名结构体A有没有声明Name字段,如果有就调用,如果没有继续查找..........如果都找不到就报错(如果A里面还有嵌入结构体那么就可以调用)
(4)当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法可以通过匿名结构体名来区分
type A struct {
Name string
age int
}
func (a *A) SayName() {
fmt.Println("A say name", a.Name)
}
func (a *A) sayAge() {
fmt.Println("A say age", a.age)
}
type B struct {
sex string
Name string
A
}
func (b *B) SayName() {
fmt.Println("B say name", b.Name)
}
func main() {
b := &B{
sex: "male",
Name: "jerry",
A: A{
Name: "lucas",
age: 29,
},
}
b.SayName()
fmt.Println(b.Name)
}
B say name jerry
jerry
可以看到B在找字段的时候已经找到了自身的字段Name,那么就不会去找A里面的Name字段。
(5)结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。
package main
import "fmt"
type A struct {
Name string
age int
}
func (a *A) SayName() {
fmt.Println("A say name", a.Name)
}
type B struct {
Name string
sex string
}
func (b *B) SayName() {
fmt.Println("B say name", b.Name)
}
type C struct {
A
B
}
func main() {
c := &C{
A: A{
Name: "lucas",
age: 23,
},
B: B{
Name: "jerry",
sex: "male",
},
}
c.A.SayName()
fmt.Println(c.A.Name)
}
(6)如果一个struct嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字
(7)嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值。