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

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 =
w.Y =
w.Radius =
w.Spokes =

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

type Point struct{
x,y int
} type Circle struct{
Center Point
Radius int
} type Wheel struct{
Circle Ciecle
Spokes int
}

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

    var    w Wheel
w.Circle.Center.X =
w.Circle.Center.Y =
w.Circle.Radius =
w.Spokes =

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

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

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

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

在右边的注释中给出的显式形式访问这些叶子成员的语法依然有效,因此匿名成员并不是真 的无法访问了。其中匿名成员Circle和Point都有自己的名字——就是命名的类型名字——但是 这些名字在点操作符中是可选的。我们在访问子成员的时候可以忽略任何匿名成员部分。
不幸的是,结构体字面值并没有简短表示匿名成员的语法, 因此下面的语句都不能编译通 过:

w = Wheel{, , , }  //compile error: unknown fields
w = Wheel{X:, Y:, Radius:, Spokers:} //compile error: unknown fields
w = Wheel{Circle{Point{,}, },}
w = Wheel{ Circle: Circle{
Point: Point{X:,Y:},
Radius: ,
},
Spokes: , // NOTE: trailing comma necessary here (and at Radius)
}
fmt.Printf("%#v\n",w)
// Output:
// Wheel{Circle:Circle{Point:Point{X:8, Y:8}, Radius:5}, Spokes:20} w.X = fmt.Printf("%#v\n", w) // Output:
// Wheel{Circle:Circle{Point:Point{X:42, Y:8}, Radius:5}, Spokes:20}

需要注意的是Printf函数中%v参数包含的#副词,它表示用和Go语言类似的语法打印值。对于 结构体类型来说,将包含每个成员的名字。

因为匿名成员也有一个隐式的名字,因此不能同时包含两个类型相同的匿名成员,这会导致 名字冲突。同时,因为成员的名字是由其类型隐式地决定的,所有匿名成员也有可见性的规 则约束。在上面的例子中,Point和Circle匿名成员都是导出的。即使它们不导出(比如改成小 写字母开头的point和circle),我们依然可以用简短形式访问匿名成员嵌套的成员

w.X =     //    equivalent    to w.circle.point.X = 8

但是在包外部,因为circle和point没有导出不能访问它们的成员,因此简短的匿名成员访问语 法也是禁止的。

到目前为止,我们看到匿名成员特性只是对访问嵌套成员的点运算符提供了简短的语法糖。 稍后,我们将会看到匿名成员并不要求是结构体类型;其实任何命名的类型都可以作为结构 体的匿名成员。但是为什么要嵌入一个没有任何子成员类型的匿名成员类型呢?
答案是匿名类型的方法集。简短的点运算符语法可以用于选择匿名成员嵌套的成员,也可以 用于访问它们的方法。实际上,外层的结构体不仅仅是获得了匿名成员类型的所有成员,而 且也获得了该类型导出的全部的方法这个机制可以用于将一个有简单行为的对象组合成有 复杂行为的对象。组合是Go语言中面向对象编程的核心。

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

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

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

  2. golang 结构体中的匿名接口

    golang 结构体中的匿名接口 代码示例 golang 中,可以给结构体增加匿名field,可参考 unknwon 大神的书. 匿名字段和内嵌结构体 但,golang同时也可以给结构体定义一个匿名i ...

  3. 【转】golang 结构体和方法

    原文:https://www.jianshu.com/p/b6ae3f85c683 ---------------------------------------------------------- ...

  4. Golang结构体struct的使用(结构体嵌套, 匿名结构体等)

    转自: https://studygolang.com/articles/11313 golang中是没有class的,但是有一个结构体struct,有点类似,他没有像java,c++中继承的概念,但 ...

  5. OC基础--结构体 枚举做类成员属性

    结构体  枚举作类的成员属性: 定义一个学生类 性别 -- 枚举 生日 入学日期  毕业日期  --  结构体 代码示例: 声明文件 Student.h: #import <Foundation ...

  6. go语言之进阶篇结构体指针类型匿名字段

    1.结构体指针类型匿名字段 示例: package main import "fmt" type Person struct { name string //名字 sex byte ...

  7. golang结构体json格式化的时间格式

    golang结构体json格式化的时间格式 在我们开发中,经常会解析time.Time 往往前台传过来的时候,是个string 但是我们希望在结构体转成time.Time type Param str ...

  8. Golang结构体值的交换

    Golang结构体值的交换 一.添加结构体,多if暴力 最先遇到这个问题是在比编写PUT方法的接口时遇到. (我公司编写http put方法,是先解析json至StudentInput结构体中,通过i ...

  9. [Go] golang结构体成员与函数类型

    package main import ( "fmt" ) //定义一个类型 type tsh struct { //定义成员,类型是func() string test func ...

随机推荐

  1. Selenium 2自动化测试实战23(窗口截图)

    一.窗口截图 WebDriver提供了截图函数get_screenshot_as_file()来截取当前窗口. # -*- coding: utf-8 -*- from selenium import ...

  2. Linux 服务器基本优化

    一:修改ulimit数 vi /etc/security/limits.conf 添加如下行: * soft noproc 65535 * hard noproc 65535 * soft nofil ...

  3. ORACLE 11G使用用EXPDP导出时,空表不能导出

    11G中有个新特性,当表无数据时,不分配segment,以节省空间解决方法:1.insert一行,再rollback就产生segment了.该方法是在在空表中插入数据,再删除,则产生segment.导 ...

  4. Mysql:常用操作(导入数据,用户授权,远程连接授权,设置通信缓冲区的最大长度)

    1.导入数据命令: mysql --host=localhost --port=3306 --user=root --password=hnsjt_lwsj@2018 szyszx_20180515- ...

  5. vue2-org-tree 基于VUE的部门组织架构组件,增删节点实现

    本文所用组件传送门:vue-org-tree 本文基于antd (其他前端组件框架操作基本都类似的: iview,elementui,boostrap-vue...) 当然,github上还有其他类似 ...

  6. 二 MyBatis 从入门到进阶 2 Maven 入门

    1 Maven 的使用 1.1 本地仓库与中央仓库 本地仓库:Window \ Preferences \ Maven \ User Settings \ Local Repository 中央仓库: ...

  7. CNN卷积汇总

    1,卷积作用:减少参数(卷积核参数共享),卷积过程中不断对上一个输出进行抽象,由局部特征归纳为全局特征(不同卷积层可视化可以观察到这点) 2,卷积核 早期卷积核由人工总结,如图像处理中有: 深度神经网 ...

  8. mysql --single-transaction 在从库导入完数据以后要在配置文件/etc/my.cnf 中加上read_only=1的参数

    1.在做数据库的主从时,防止在这个过程中,有数据访问进来,要: 要想连super权限用户的写操作也禁止,就使用"flush tables with read lock;",这样设置 ...

  9. 再谈js对象数据结构底层实现原理-object array map set

    如果有java基础的同学,可以回顾下<再谈Java数据结构—分析底层实现与应用注意事项>:java把内存分两种:一种是栈内存,另一种是堆内存.基本类型(即int,short,long,by ...

  10. 显示 隐藏 加减css

    < script type = "text/javascript" > $(document).ready(function() { $("#hide1&qu ...