英文:
What is the purpose of emedding a struct in a field (golang)?
问题
根据下面的示例,似乎"在字段中嵌入结构体"的目的是为了打破Go语言的"提升"机制。为什么要这样做呢?
type obj1 struct {
obj2
}
type obj1Selector struct {
selector obj2
}
type obj2 struct {
}
func (o obj2) printTest() {
fmt.Println("obj2")
}
func main() {
o := obj1{}
o.printTest() // 正常
oSelector := obj1Selector{}
oSelector.selector.printTest() // 正常
oSelector.printTest() // 不正常
}
以上代码中,obj1
结构体嵌入了obj2
结构体,而obj1Selector
结构体则包含了一个名为selector
的obj2
类型字段。通过调用printTest()
方法,我们可以看到在obj1
类型的实例上调用是正常的,而在obj1Selector
类型的实例上调用则会报错。这是因为在obj1Selector
中,obj2
类型的字段没有被提升到外部结构体的作用域,所以无法直接访问。这种方式可以用来避免字段的提升,从而实现更精确的控制。
英文:
Based on the below sample it seems that the point of "embedding an struct in a field" is to break Go's "promotion" mechanism. Why would you want to do this?
type obj1 struct {
obj2
}
type obj1Selector struct {
selector obj2
}
type obj2 struct {
}
func (o obj2) printTest() {
fmt.Println("obj2")
}
func main() {
o := obj1{}
o.printTest() //fine
oSelector := obj1Selector{}
oSelector.selector.printTest() //fine
oSelector.printTest() //not fine
答案1
得分: 1
你没有给任何东西起别名,选择器是指可以使用点表示法引用类型上的一组事物。你正在使用一种称为嵌入的概念,obj1
嵌入了obj2
。obj1Selector
有一个名为selector
的字段,类型为obj2
。别名的写法是这样的:type obj3 obj2
,它将obj3
声明为obj2
的别名。
这会破坏Go的提升机制吗?抱歉,但你对这个机制的整体理解是错误的。obj1Selector
并没有嵌入类型obj2
,因此没有从obj2
“提升”的字段/方法,obj1
嵌入了obj2
,因此它的字段/方法被“提升”了。obj1Selector
并没有实现该接口,obj1Selector.selector
实现了。
为什么我要使用嵌入?嗯,这在某种程度上相当于继承,或者至少在使用Go进行开发时提供了类似的功能集。也许我在数据存储中有许多记录,它们共享10个常见字段,然后有另外10个字段,这些字段取决于它们来自哪个表。就像我在典型的面向对象语言(如C++、C#或Java)中使用继承来减少重复一样,我会在Go中使用嵌入。在我看来,这是它的主要用途。它有点像组合和继承的奇怪混合。你在组合其他对象(你嵌入的对象)的同时,由于嵌入类型的方法/字段被提升到嵌入者的作用域,它的功能很像嵌入者从嵌入类型继承过来。希望这能对你在这里处理的内容有一些澄清...你并没有提出一个可以回答的问题,但在评论中没有足够的空间来解释你在示例代码中使用的特性/概念。
英文:
You're not aliasing anything and selectors refer to the set of things that can be referenced on a type using dot notation. You're using a concept called embedding, obj1
embeds obj2
. obj1Selector
has a single field called selector
of type obj2
. And alias would look like this; type obj3 obj2
which declares obj3
as an alias for obj2
.
It breaks Go's promotion mechanism? Sorry but your whole idea of how this works is off basis. obj1Selector
does not embed the type obj2
and therefor has no field/methods from obj2
'promoted', obj1
embeds obj2
and therefor has it's fields/methods 'promoted'. obj1Selector
does not implement that interface, obj1Selector.selector
does.
Why would I want to embed? Well it's somewhat equivalent to inheritance or at least provides a similar feature set when developing in Go. Perhaps I have a number of records in a data store that all share 10 common fields and then have another 10 fields that depend on which table they came off of. Just as I'd use inheritance to reduce duplication in typical OO languages like C++, C# or Java I would use embedding in Go. In my opinion that is the main use case for it. It's sort of a weird mix of composition and inheritance. You're composing on object of others (the ones you're embedding) but since the embedded types methods/fields are promoted to the embedors scope it functions a lot like if the embedor inherited from the embedded type. Hope that gives some clarification as to what you're dealing with here... You haven't really posed a question that can be answered but there isn't space in the comments for such a lengthy explanation of the features/concepts you're using your sample code.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论