嵌入结构体在字段中的目的是什么?(golang)

huangapple go评论90阅读模式
英文:

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结构体则包含了一个名为selectorobj2类型字段。通过调用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嵌入了obj2obj1Selector有一个名为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.

huangapple
  • 本文由 发表于 2016年4月13日 02:40:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/36581469.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定