【发布时间】:2015-01-01 19:19:33
【问题描述】:
当我想在另一个结构中嵌入一个结构时,我应该使用指针还是值?
例如
type Job struct {
Command string
*log.Logger
}
或
type Job struct {
Command string
log.Logger
}
【问题讨论】:
当我想在另一个结构中嵌入一个结构时,我应该使用指针还是值?
例如
type Job struct {
Command string
*log.Logger
}
或
type Job struct {
Command string
log.Logger
}
【问题讨论】:
您可以使用其中一个:对于struct type,规范提到:
使用类型声明但没有显式字段名称的字段是 匿名 字段,也称为 嵌入 字段或该类型在结构中的嵌入。
必须将嵌入类型指定为类型名称
T或指向非接口类型名称*T的指针,而T本身可能不是指针类型。
由于log.Logger不是接口,您可以使用类型或指向匿名字段Logger的类型的指针。
Eric Urban (hydrogen18) 的文章“Embedding in Go ”称嵌入指针“embed by-pointer”:
- 这样做的第一个好处是,您可以依赖使用
NewX惯用语返回结构体指针的函数进行初始化。- 第二个优点是您可以嵌入一个类型的所有功能,而无需知道它何时被实例化。
指向Bitmap的嵌入指针与 Go 中的任何其他指针没有什么不同,因此可以多次分配。
通过这样做,您可以更改在运行时动态扩展的实例。
例如,用:
type Bitmap struct{
data [4][5]bool
}
type Renderer struct{
*Bitmap //Embed by pointer
on uint8
off uint8
}
Renderer 类型嵌入了 Bitmap 指针。
Bitmap的单个实例可以充当许多Renderer实例的嵌入实例:
var renderA,renderB Renderer
renderA.on = 'X'
renderA.off = 'O'
renderB.on = '@'
renderB.off = '.'
var pic Bitmap
pic.data[0][6] = true
pic.data[0][7] = true
pic.data[1][8] = true
pic.data[2][9] = true
pic.data[3][10] = true
renderA.Bitmap = &pic
renderB.Bitmap = &pic
renderA.render()
renderB.render()
这会将同一个
Bitmap实例共享给两个不同的渲染器。
每个渲染器都有自己的一组字符,允许打印位图的两种表示形式。
这是输出的样子:
OXXO
OXOO
OXOO
OXOO
.@@.
.@..
.@..
.@..
这个例子演示了Flyweight Pattern。
尽管在此示例中对内存消耗无关紧要,但让数千个实例共享一个底层数据结构对于减少系统的内存消耗非常重要。
如this thread中所述:
你不能有指向指针和指向接口匿名字段的指针的原因是这些类型没有方法。
匿名字段的全部意义在于方法得到提升。我已经解释了为什么接口没有方法:很多人错误且不必要地使用了指向接口的指针,并且没有任何已知的有效用途,因此更改了语言以通过制作指针来积极阻止这种用法to 接口没有方法。
【讨论】:
as a pointer to a non-interface type name *T 这是什么意思?
The whole point of anonymous fields is that methods get promoted. 提升是什么意思?
*log.Logger 是一个指向非接口类型的指针:它可以嵌入。