定义一个struct,定义的时候是字段名与其类型一一对应,实际上Go语言支持只提供类型,而不写字段名的方式,也就是匿名字段,或称为嵌入字段。

当匿名字段是一个struct的时候,那么这个struct所拥有的全部字段以及方法(指绑定在这个类型上的,见最后)都被隐式地引入了当前定义的这个struct。

让我们来看一个例子,让上面说的这些更具体化。

package mainimport "fmt"type Human struct {name stringage intweight int}type Student struct {Human  // 匿名字段,那么默认Student就包含了Human的所有字段speciality string}func main() {// 我们初始化一个学生mark := Student{Human{"Mark", 25, 120}, "Computer Science"}// 我们访问相应的字段fmt.Println("His name is ", mark.name)fmt.Println("His age is ", mark.age)fmt.Println("His weight is ", mark.weight)fmt.Println("His speciality is ", mark.speciality)// 修改对应的备注信息mark.speciality = "AI"fmt.Println("Mark changed his speciality")fmt.Println("His speciality is ", mark.speciality)// 修改他的年龄信息fmt.Println("Mark become old")mark.age = 46fmt.Println("His age is", mark.age)// 修改他的体重信息fmt.Println("Mark is not an athlet anymore")mark.weight += 60fmt.Println("His weight is", mark.weight)}

图2.7  Student和Human的方法继承的内存结构

我们看到Student访问属性age和name的时候,就像访问自己所有用的字段一样,对,匿名字段就是这样,能够实现字段的继承。是不是很酷?还有比这个更酷的呢!那就是student还能访问Human这个字段作为字段名,请看下面的代码。

mark.Human = Human{"Marcus", 55, 220}mark.Human.age -= 1

通过匿名访问和修改字段很有用,但不仅仅是struct字段,所有的内置类型和自定义类型都可以作为匿名字段。请看下面的例子。

package mainimport "fmt"type Skills []stringtype Human struct {name stringage intweight int}type Student struct {Human  // 匿名字段,structSkills // 匿名字段,自定义的类型string sliceint    // 内置类型作为匿名字段speciality string}func main() {// 初始化学生Janejane := Student{Human:Human{"Jane", 35, 100}, speciality:"Biology"}// 现在我们来访问相应的字段fmt.Println("Her name is ", jane.name)fmt.Println("Her age is ", jane.age)fmt.Println("Her weight is ", jane.weight)fmt.Println("Her speciality is ", jane.speciality)// 我们来修改他的skill技能字段jane.Skills = []string{"anatomy"}fmt.Println("Her skills are ", jane.Skills)fmt.Println("She acquired two new ones ")jane.Skills = append(jane.Skills, "physics", "golang")fmt.Println("Her skills now are ", jane.Skills)// 修改匿名内置类型字段jane.int = 3fmt.Println("Her preferred number is", jane.int)}

  

从上面例子可见,struct不仅能将struct作为匿名字段,自定义类型、内置类型都可以作为匿名字段,而且可以在相应的字段上进行函数操作(如例子中的append)。

有个问题:如果human里面有一个字段叫做phone,而student也有一个字段叫做phone,那么该怎么办呢?

Go语言很简单地解决了这个问题,最外层的优先访问,也就是当你通过student.phone访问的时候,是访问student里面的字段,而不是human里面的字段。

这样就允许我们去重载通过匿名字段继承的一些字段,当然如果我们想访问重载后对应匿名类型里面的字段,可以通过匿名字段名来访问。请看下面的例子。

package mainimport "fmt"type Human struct {name stringage intphone string  // Human类型拥有的字段}type Employee struct {Human  // 匿名字段Humanspeciality stringphone string  // 雇员的phone字段}func main() {Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}fmt.Println("Bob's work phone is:", Bob.phone)// 如果我们要访问Human的phone字段fmt.Println("Bob's personal phone is:", Bob.Human.phone)}

  

关于对方法的继承,看一段的代码对比就比较明了了:

package mainimport ("fmt"
)type Animal struct {Age int
}type Person struct {AnimalSex int}func (animal Animal) getName() string {return "animal"
}// func (person Person) getName() string {
//  return "person"
// }func main() {var animal Animalvar person Personfmt.Println(animal.getName())fmt.Println(person.getName())
}
// 输出
// animal
// animal

  

package mainimport ("fmt"
)type Animal struct {Age int
}type Person struct {AnimalSex int}func (animal Animal) getName() string {return "animal"
}func (person Person) getName() string {return "person"
}func main() {var animal Animalvar person Personfmt.Println(animal.getName())fmt.Println(person.getName())
}
// 输出
// animal
// persion

  最后,如果匿名字段是指针的话,那么只是占一个指针的大小:

package main
import "fmt"
import "unsafe"type T struct {a intb float64
}type A struct{T
}type B struct{*T
}func main() {var t Tvar a Avar b Bfmt.Println(unsafe.Sizeof(t))fmt.Println(unsafe.Sizeof(a))fmt.Println(unsafe.Sizeof(b))var x *Tfmt.Println(unsafe.Sizeof(x))
}
// 输出:
// 16
// 16
// 8
// 8

  

转载于:https://www.cnblogs.com/maji233/p/11059589.html

Golang 匿名字段相关推荐

  1. GoLang之结构体匿名字段

    文章目录 1.结构体内嵌套匿名结构体(访问相同字段) 2.结构体内嵌套匿名结构体(访问相同方法) 3.结构体嵌套匿名自定义类型 4.结构体嵌套匿名内置类型 5.结构体嵌套任意类型匿名指针 6.匿名结构 ...

  2. GO学习笔记:struct的匿名字段

    我们上面介绍了如何定义一个struct,定义的时候是字段名与其类型一一对应,实际上Go支持只提供类型,而不写字段名的方式,也就是匿名字段,也称为嵌入字段. 当匿名字段是一个struct的时候,那么这个 ...

  3. golang匿名组合

    匿名组合 匿名字段 一般情况下,定义结构体的时候是字段名和其类型一一对应,实际上go支持只提供类型而不写字段名的方法,也就是匿名字段,也称为嵌入式字段 当匿名字段也是一个结构体的时候,那么这个结构体所 ...

  4. 兄弟连go教程(19)数据 - 匿名字段

    匿名字段不过是⼀一种语法糖,从根本上说,就是⼀一个与成员类型同名 (不含包名) 的字段. 被匿名嵌⼊入的可以是任何类型,当然也包括指针. type User struct { name string ...

  5. Golang 匿名结构体及测试代码编写技巧

    转自: https://www.jianshu.com/p/901820e17ffb 结构体基础 结构体 (struct) 将多个不同类型的字段集中组成一种复合类型,按声明时的字段顺序初始化. typ ...

  6. golang匿名函数

    文章目录 1. 匿名函数的声明 2. 匿名函数的作用 2.1 在定义时调用匿名函数 2.2 匿名函数可以赋值 2.3 匿名函数作为回调函数 2.4 使用匿名函数实现操作封装 3. 总结 1. 匿名函数 ...

  7. Golang匿名结构体结构体嵌套(实战使用)

    背景 最近研究钉钉机器人的时候,总是会向钉钉官方接口发送很多请求,发送请求的时候,需要封装body结构体传递参数,还要封装response结构体用来接收返回值,有时候,response结构体中还要嵌套 ...

  8. 四、golang类型讲解--go语言学习笔记

    擅自使用了七牛大牛们的PPT资料,希望不要怪罪,这里谢谢大牛们的分享. 映射 map 一个"键-值"对 关键点:注意并发读写情况,上锁 不能对未初始化的 map 进行写,会抛异常( ...

  9. golang 结构体简介

    Go 通过类型别名(alias types)和结构体的形式支持用户自定义类型,或者叫定制类型.试图表示一个现实世界中的实体. 结构体由一系列命名的元素组成,这些元素又被称为字段,每个字段都有一个名称和 ...

最新文章

  1. JSIS3D:具有多任务点向网络和多值条件随机场的3D点云联合语义-实例分割
  2. TC264信标组 双车组 资源规划 库函数示例
  3. 快手,字节面试题,将IP地址转换成整数类型,再转换回来。C++代码
  4. think in java - 第四章 学习笔记
  5. pytorchyolov4训练_使用pytorch-yolov5 訓練自己的數據集-2020.6.15
  6. c语言风景日历制作系统,初学,C语言日历制作
  7. PHP经验——获得PHP版本信息及版本比较
  8. 关于redis说法正确的是_还不会正确使用Redis?这几个技巧让你的程序快如闪电...
  9. Spyder5.3.3无法使用下载好的库
  10. 印象笔记导入html笔记,Evernote Importer|印象笔记导入
  11. 可以在手机预览ps设计稿的软件
  12. 使用uiautomation 实现微信自动发送消息
  13. 批处理中 %~d0 cd %~dp0 的含义
  14. 用DEV-C++制作狼人杀
  15. 第五章第五题(千克与磅之间的互换)(Conversion from kilogram to pound and pound to kilogram)
  16. 双活数据中心架构分析及优缺点
  17. Python+Vue计算机毕业设计教师教学质量评价管理2lbw7(程序+LW+源码+部署)
  18. 从技术小白到收获BAT研发offer,分享我的学习经验和感悟(赠送相关学习资料)
  19. java调用kettle自定义kettle.properties配置文件路径
  20. 计算机不接受跨专业考研,2016跨专业考研需谨慎的专业解读:计算机

热门文章

  1. Java Web项目实战案例一
  2. 虚拟服务器安装管理工具,easypanel虚拟主机管理面板v1.9.2安装版-虚拟主机管理软件...
  3. Java使用Aspose组件进行多文档间的转换操作
  4. 下载安装及编写第一个C语言程序Visual Studio 2019
  5. 数据库 主键 外键 唯一键区别
  6. GnuTLS recv error (-54): Error in the pull function.
  7. RIP原理、毒性反转原理与应用【eNSP实现】
  8. 单片机+DHT11的温湿度采集监测系统,LCD1602显示,带报警功能,C代码、原理图和Proteus仿真
  9. 命令行运行Unity脚本
  10. 2021年中国电视节目产量、播出时间及电视节目综合人口覆盖率分析[图]