英文:
Embedding when to use pointer
问题
当我想在一个结构体中嵌入另一个结构体时,我应该使用指针还是值?
例如:
type Job struct {
Command string
*log.Logger
}
还是
type Job struct {
Command string
log.Logger
}
英文:
When I want to embed a struct within another struct, should I use a pointer or value?
For example
type Job struct {
Command string
*log.Logger
}
or
type Job struct {
Command string
log.Logger
}
答案1
得分: 13
你可以使用其中之一:对于struct类型,规范中提到:
使用类型但没有显式字段名声明的字段是匿名字段,也称为嵌入字段或将类型嵌入结构中的字段。
嵌入类型必须指定为类型名
T
或非接口类型名*T
的指针,并且T
本身不能是指针类型。
由于log.Logger
不是接口,你可以对匿名字段Logger
使用类型或类型的指针。
文章“在Go中嵌入”来自Eric Urban (hydrogen18
),将指针嵌入称为“通过指针嵌入”:
- 这样做的第一个优点是,你可以依赖使用
NewX
惯用法返回指向结构体的指针的函数进行初始化。
- 第二个优点是,你可以嵌入类型的所有功能,而无需知道何时实例化它。
指向Bitmap
的嵌入指针与Go中的任何其他指针没有区别,因此可以多次赋值。
通过这样做,你可以在运行时动态更改要扩展的实例。
例如,使用以下代码:
type Bitmap struct{
data [4][5]bool
}
type Renderer struct{
*Bitmap //通过指针嵌入
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
.@@.
.@..
.@..
.@..
这个示例演示了享元模式。
虽然在这个示例中对内存消耗没有影响,但是许多共享单个底层数据结构的实例可以在减少系统内存消耗方面非常重要。
如此线程中所述:
不能将指针嵌入和接口指针嵌入作为匿名字段的原因是这些类型没有方法。
匿名字段的整个目的是方法的提升。
我已经解释过为什么接口没有方法:很多人错误地和不必要地使用指向接口的指针,而且没有已知的有效用途,因此通过使指向接口的指针没有方法来主动阻止这种用法,从而改变了语言。
英文:
You can use one or the other: for struct type, the spec mentions:
> A field declared with a type but no explicit field name is an anonymous field, also called an embedded field or an embedding of the type in the struct.
> An embedded type must be specified as a type name T
or as a pointer to a non-interface type name *T
, and T
itself may not be a pointer type.
Since log.Logger
is not an interface, you can use the type or a pointer to the type for the anonymous field Logger
.
The article "Embedding in Go " fro Eric Urban (hydrogen18
) calls embedding a pointer "embed by-pointer":
> - The first advantage to this is that you can rely on functions that use the NewX
idiom returning a struct by-pointer to do initialization.
- The second advantage is that you can embed all the functionality of a type without needing to know when it is instantiated.
The embedded pointer to aBitmap
is no different than any other pointer in Go, so it can be assigned multiple times.
By doing this you can change what instance you are extending dynamically at run time.
For instance, with:
type Bitmap struct{
data [4][5]bool
}
type Renderer struct{
*Bitmap //Embed by pointer
on uint8
off uint8
}
The Renderer
type embeds a Bitmap
by-pointer.
> A single instance of Bitmap
can act as the embedded instance of many Renderer
instances:
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()
> This shares the same Bitmap
instance to two different renderers.
Each renderer has its own set of characters, allowing two representations of the bitmap to be printed.
This is what the output looks like:
OXXO
OXOO
OXOO
OXOO
.@@.
.@..
.@..
.@..
> This example demonstrates the Flyweight Pattern.
Although inconsequential to memory consumption in this example, having many thousands of instances sharing a single underlying data structure can be very significant in reducing the memory consumption of systems.
As mentioned in this thread:
> The reason why you can't have pointer to pointer and pointer to interface anonymous fields is that these types don't have methods.
The whole point of anonymous fields is that methods get promoted.
> I already explained why interfaces don't have methods: a lot of people were using pointers to interfaces incorrectly and unnecessarily, and there weren't any known valid uses, so the language was changed to actively discourage this usage by making pointers to interfaces have no methods.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论