考虑一个二维的绘图程序,提供了一个各种图形的库,例如矩形、椭圆形、星形和轮形等几何形状。这里是其中两个的定义:

type Circle struct {
  X, Y, Radius int
}
type Wheel struct {
  X, Y, Radius, Spokes int
}

一个Circle代表的圆形类型包含了标准圆心的X和Y坐标信息,和一个Radius表示的半径信息。一个Wheel轮形除了包含Circle类型所有的全部成员外,还增加了Spokes表示径向辐条的数量。我们可以这样创建一个wheel变量:

var w Wheel
w.X = 8
w.Y = 8
w.Radius = 5
w.Spokes = 20

随着库中几何形状数量的增多,我们一定会注意到它们之间的相似和重复之处,所以我们可能为了便于维护而将相同的属性独立出来:

ype Point struct {
  X, Y int
}
type Circle struct {
  Center Point
  Radius int
}
type Wheel struct {
  Circle Circle
  Spokes int
}

这样改动之后结构体类型变的清晰了,但是这种修改同时也导致了访问每个成员变得繁琐:

var w Wheel
w.Circle.Center.X = 8
w.Circle.Center.Y = 8
w.Circle.Radius = 5
w.Spokes = 20

Go语言有一个特性让我们只声明一个成员对应的数据类型而不指名成员的名字;这类成员就叫匿名成员。匿名成员的数据类型必须是命名的类型或指向一个命名的类型的指针。下面的代码中,Circle和Wheel各自都有一个匿名成员。我们可以说Point类型被嵌入到了Circle结构体,同时Circle类型被嵌入到了Wheel结构体。

type Circle struct {
  oint
  Radius int
}
type Wheel struct {
  Circle
  Spokes int
}

得意于匿名嵌入的特性,我们可以直接访问叶子属性而不需要给出完整的路径:

var w Wheel
w.X = 8 // equivalent to w.Circle.Point.X = 8
w.Y = 8 // equivalent to w.Circle.Point.Y = 8
w.Radius = 5 // equivalent to w.Circle.Radius = 5
w.Spokes = 20

在右边的注释中给出的显式形式访问这些叶子成员的语法依然有效,因此匿名成员并不是真的无法访问了。其中匿名成员Circle和Point都有自己的名字——就是命名的类型名字——但是这些名字在点操作符中是可选的。我们在访问子成员的时候可以忽略任何匿名成员部分。

不幸的是,结构体字面值并没有简短表示匿名成员的语法, 因此下面的语句都不能编译通过:

w = Wheel{8, 8, 5, 20} // compile error: unknown fields
w = Wheel{X: 8, Y: 8, Radius: 5, Spokes: 20} // compile error: unknown fields

结构体字面值必须遵循形状类型声明时的结构,所以我们只能用下面的两种语法,它们彼此是等价的:

w = Wheel{Circle{Point{8, 8}, 5}, 20}
w = Wheel{
Circle: Circle{
Point: Point{X:8, Y:8},
Radius: 5,
},
Spokes: 20,
}

golang之结构体结构体嵌入和匿名成员的更多相关文章

  1. golang 结构体嵌入和匿名成员

    考虑一个二维的绘图程序,提供了一个各种图形的库,例如矩形.椭圆形.星形和轮形等几 何形状.这里是其中两个的定义 type Circle struct { X, Y, Radius int } type ...

  2. Golang通过反射获取结构体的标签

    Golang通过反射获取结构体的标签 例子: package main import ( "fmt" "reflect" ) type resume struc ...

  3. C#调用C/C++动态库 封送结构体,结构体数组

    一. 结构体的传递 #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数 typedef struct { int ...

  4. 瘋子C语言笔记(结构体/共用体/枚举篇)

    (一)结构体类型 1.简介: 例: struct date { int month; int day; int year; }; struct student { int num; char name ...

  5. C++结构、共用体、枚举

    一.结构 结构是C++OOP的基石.学习有关结构的知识僵尸我们离C++的核心OOP更近. 结构是用户定义的类型,同一个结构可以存储多种类型数据,这使得将一个事物的不同属性构成一个对象成为了可能.另外C ...

  6. Swift超详细的基础语法-结构体,结构体构造器,定义成员方法, 值类型, 扩充函数

    知识点 基本概念 结构体的基本使用 结构体构造器(构造函数/构造方法) 结构体扩充函数(方法), 又称成员方法 结构体是值类型 1. 基本概念 1.1 概念介绍 结构体(struct)是由一系列具有相 ...

  7. FrameBuffer系列 之 相关结构与结构体

    在linux中,fb设备驱动的源码主要在Fb.h (linux2.6.28\include\linux)和Fbmem.c(linux2.6.28\drivers\video)两个文件中,它们是fb设备 ...

  8. update_engine-整体结构(三)

    在update_engine-整体结构(二)中分析到了Action,那么我们接着继续分析. 首先来看一下BuildUpdateActons(...)这个方法. src/system/update_en ...

  9. update_engine-整体结构(二)

    在update_engine-整体结构(一)中分析UpdateEngineDaemon::OnInit()的整体情况.下面先分析在该方法中涉及的DaemonStateAndroid和BinderUpd ...

随机推荐

  1. Ubuntu16.04忘记MySQL5.7的root用户密码之解决方案

    其实也就四步,如下: 修改配置文件 sudo vimi /etc/mysql/mysql.conf.d/mysqld.cnf 并在 在[mysqld]下方的skip-external-locking下 ...

  2. 2019-暑假作业-Java语言程序设计

    本文于2017年创建,最后更新2019-07-16 任务列表 1.学会使用Markdown做笔记 本篇随笔就是使用的Markdown语法.养成做笔记的习惯! 参考资料: 极简MarkDown排版介绍( ...

  3. JVM内存空间划分与作用

    虚拟机栈:Stack Fame 栈桢 程序计数器(Program Counter): 本地方法栈:主要用于处理本地方法 堆(Heap): JVM管理的最大一块内存空间 方法区(Method Area) ...

  4. itop 环境

    iTop,即IT运营门户(IT Operation Portal),是一个开源web应用程序,用于IT环境的日常运营.它基于ITIL最佳实践,而又不拘泥于任何具体流程.它很灵活,可以适应不管是非正 式 ...

  5. bat和cmd文件是什么,dos又是什么东西

    bat文件是dos下的批处理文件.批处理文件是无格式的文本文件,它包含一条或多条命令.它的文件扩展名为 .bat 或 .cmd.在命令提示下键入批处理文件的名称,或者双击该批处理文件,系统就会调用cm ...

  6. Mysql修改数据文件默认目录datadir

    1.停止服务 service mysql stop service mysqld stopmysqladmin -uroot shutdown -p 2.创建目录 cd /data mkdir mys ...

  7. 效率包括了代码的GC 大小与内存大小,执行速度等等。其中执行速度不是关注 的重点

    效率包括了代码的GC 大小与内存大小,执行速度等等.其中执行速度不是关注的重点

  8. java使用json-lib库的json工具类.

    import net.sf.ezmorph.object.DateMorpher;import net.sf.json.JSONArray;import net.sf.json.JSONObject; ...

  9. Laya的图文混排

    参考: Laya图文混排 Laya的图文混排教程 编辑模式F9,增加laya.html.js库 在层级窗口右键,添加一个HtmlDivElement组件 大致的原理: 1. 例如输入框的字符串是 &q ...

  10. WinForm,在另一个线程中更新Form中的数据(转)

    Form本身有线程,但对于一些耗时的操作,我们不希望在Form的线程中进行,因为会导致Form线程阻塞,产生假死的现象. 其他线程中操作Form中的控件,总出现“线程间操作无效: 从不是创建控件的线程 ...