匿名组合=匿名字段

代码复用

  1. 匿名函数
  2. 结构体类型定义

匿名字段

用于结构体,很像嵌套结构体,目标是代码复用,减少冗余,也就是“继承”

定义

一般情况下,定义结构体的时候是字段名与其类型一一对应,实际上Go支持只提供类型,

而不写字段名的方式,也就是匿名字段,也称为嵌入字段。

当匿名字段也是一个结构体的时候,那么这个结构体所拥有的全部字段都被隐式地引入了当

前定义的这个结构体。

继承--结构体/方法/接口→的嵌套 - 图1

理论上可以无限嵌套下去,但不建议,因为赋值的时候会很麻烦

初始化

key:按序赋值

继承--结构体/方法/接口→的嵌套 - 图2

可以指定成员初始化,其他自动赋值为0,方法和结构体的一样字段名:值 ,需要一一对应

继承--结构体/方法/接口→的嵌套 - 图3

  1. package main
  2. import "fmt"
  3. func main() {
  4. type person struct {
  5. name string
  6. age int
  7. }
  8. type person_1 struct{
  9. person
  10. love string
  11. hate string
  12. }
  13. man_1 :=person_1{
  14. person{"justin",25},
  15. "girl", "bad luck",
  16. }
  17. fmt.Println(man_1)
  18. fmt.Printf("%v\n", man_1)
  19. fmt.Printf("%+v\n", man_1)
  20. }

NOTE:

可以使用new函数进行初始化, 但由于嵌套形态不一, 并不推荐

调用

:::info

:::

打印

继承--结构体/方法/接口→的嵌套 - 图4

  1. println(man_1)
  2. printf
    1. printf("%v",man_1)println(man_1)效果相同
    2. printf("%+v",man_1)会打印出更详细的信息

:::info

:::

赋值

  1. .成员运算符
    1. 和结构体一样,man_1.name
      匿名字段部分亦可直接调用,无需man_1.person.name(除非同名字段)
    2. 匿名字段还可以整体赋值,man_1.person = person{...}
  2. 统一赋值
    等式右边——person_1{...}

:::info 同名字段

:::

同名字段

key:默认就近原则
继承--结构体/方法/接口→的嵌套 - 图5

若需要赋值匿名字段的同名字段,则需要man_1.person.age

继承--结构体/方法/接口→的嵌套 - 图6

这里揭示了成员运算符的机制

  1. 先在本作用域,搜索字段,索不到,再在匿名字段里搜索,无需码农再加匿名字段
  2. 同名字段,遵循就近原则;若需要赋值匿名字段的同名字段,则需要加上匿名字段

应用

非结构体匿名字段

结构体中,只写类型,不写名,比如图中基础类型的匿名字段

  1. 初始化依旧
    继承--结构体/方法/接口→的嵌套 - 图7继承--结构体/方法/接口→的嵌套 - 图8
  2. 成员运算符怎么弄呢?——s.int直接写类型名
    继承--结构体/方法/接口→的嵌套 - 图9

结构体指针类型的匿名字段

本质上,和原来的结构体指针没差别,我们下面来看一些语法上的操作

  1. 结构体就加个*
  2. 初始化
    1. 直接赋值
      继承--结构体/方法/接口→的嵌套 - 图10
      结果
      继承--结构体/方法/接口→的嵌套 - 图11
    2. 先分配空间,等式右边——new(person)/ Person{}
      继承--结构体/方法/接口→的嵌套 - 图12

综合

  1. 结构体定义进行继承,
    1. 结构体成员访问也就继承了
    2. 方法就带着进行继承
  2. 接口的定义继承了,方法也就带着继承了