Golang嵌入式结构 [英] Golang embedded struct

查看:762
本文介绍了Golang嵌入式结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能在不使用嵌入式结构的情况下继承一个类型的方法?



代码的第一部分是嵌入属性的工作代码 struct Node ,我可以调用 node.GetString 这是一种方法属性。我不喜欢这件事的是当我初始化 Node 我有(?)初始化属性结构在它之内。有没有解决的办法?

 包主

导入fmt

类型属性map [字符串]接口{}

func(p属性)GetString(键字符串)字符串{
返回p [键]。(字符串)
}

类型节点map [string] *节点

类型节点struct {
*属性
}

func main(){
allNodes :=节点{1:& Node {& Properties {test:foo}}} //:'(
singleNode:= allNodes [1]
fmt。 Println(singleNode.GetString(test))
}

最终,我想做如下的事情: Node 的类型是 Properties ,并且初始化不需要初始化一个 Property struct too。以下代码不起作用,但可能会清楚我的目标是什么。

  b 







func(p属性)GetString(key字符串)字符串{
return p [key]。(string)
}

类型节点map [string] *节点

节点属性

func main(){
allNodes:= Nodes {1:& Node {test:foo}} // :)
singleNode:= allNodes [1 ]
fmt.Println(singleNode.GetString(test))//:D
}

我将添加更多的结构,这些结构将使用 Properties 的方法,这就是为什么我要问。如果我只有 Node ,我只需要 Node 的方法并完成。但是因为我将拥有超过 Node 我发现将相同的方法添加到嵌入 Properties
我想更确切的问题是,我想从<$ c $使用 Properties 方法c> Node
无需初始化 Properties

解决方案

所以你在这里遇到了Go的特质。嵌入是一个结构的方法可以被提升看起来存在于另一个结构中的唯一方法。感觉直观的是,类型的节点属性应该在 Node 上暴露属性方法c $ c>,该语法的效果是 Node 占用属性的内存布局,但不是任何它的方法。



它并没有解释为什么这个设计的选择,但 Go Spec 至少是特定的,如果干的话。如果您完全按照它的形式阅读它,而没有解释,那么它就非常准确:


接口类型的方法集是它的接口。任何其他类型T的方法集由所有声明为
且接收方类型为T的方法组成。b


$ b $ p $ GetString
有一个接收器类型为属性不是 Node ,认真地解释你的规范是一个没有想象力的会计师。这就是说:
$ b


其他规则适用于包含匿名字段的结构,如结构类型部分所述。





$ b

结构x中匿名字段的字段或方法f在xf是合法选择器时称为提升表示该字段或方法f。

升级字段的作用类似于结构的普通字段,只是它们
不能用作结构复合字面值中的字段名称。

给定一个结构类型S和一个名为T的类型,所提升的方法是
包含在struct的方法集中,如下所示:




  • 如果S包含匿名字段T,则S和* S的方法集合
    都包含带有接收方T的升级方法。方法集合* S也
    包括接收器* T的推广方法。

  • 如果S包含匿名
    字段* T,则S和* S的方法集都包含带有接收者T或* T的升级方法
    。 >

关于复合文字的这一行是强制你声明 Properties 在您创建的每个 Node 中。



ps杰夫!


Is it possible to inherit methods of a type without using embedded structs?

The first snippet of code is working code that embeds the Property struct in Node and I'm able to call node.GetString that's a method on Properties. The thing I don't like about this is when I initialize Node I have(?) to initialize the Properties struct within it. Is there a way around this?

package main

import "fmt"

type Properties map[string]interface{}

func (p Properties) GetString(key string) string {
    return p[key].(string)
}

type Nodes map[string]*Node

type Node struct {
    *Properties
}

func main() {
    allNodes := Nodes{"1": &Node{&Properties{"test": "foo"}}} // :'(
    singleNode := allNodes["1"]
    fmt.Println(singleNode.GetString("test"))
}

Ultimately, I would like to do something like the following. Where Node is of type Properties and initializing does not require initializing a Property struct too. The following code doesn't work but may be clear what my goal is.

package main

import "fmt"

type Properties map[string]interface{}

func (p Properties) GetString(key string) string {
    return p[key].(string)
}

type Nodes map[string]*Node

type Node Properties

func main() {
    allNodes := Nodes{"1": &Node{"test": "foo"}} // :)
    singleNode := allNodes["1"]
    fmt.Println(singleNode.GetString("test")) // :D
}

I'll be adding more structs that will use Properties's methods which is why I'm asking. If I only had Node, I would just have methods for Node and be done. But because I'll have more than Node I find it kind of redundant to add the same methods to all the structs that embed Properties

I guess more to the exact problem, I want to use Properties methods from Node without having to initialize Properties.

解决方案

So you're running into an idiosyncrasy of Go here. Embedding is the only way in which methods of one struct can get "promoted" to appear to exist on another struct. While it feels intuitive that type Node Properties should expose the Properties methods on Node, that effect of that syntax is for Node to take on the memory layout of Properties but not any of its methods.

It doesn't explain why this design choice was made but the Go Spec is at least specific if dry. If you read it exactly as it appears, with no interpretation, it is very accurate:

The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T

GetString has a receiver of type Properties not Node, seriously, interpret the spec like you're an accountant with no imagination. With that said:

Further rules apply to structs containing anonymous fields, as described in the section on struct types.

...

A field or method f of an anonymous field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.

Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the struct.

Given a struct type S and a type named T, promoted methods are included in the method set of the struct as follows:

  • If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
  • If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.

That line about composite literals is this thing that forces you to declare Properties inside every Node you create.

p.s. Hi Jeff!

这篇关于Golang嵌入式结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆