Golang嵌入式结构 [英] Golang embedded struct
问题描述
是否有可能在不使用嵌入式结构的情况下继承一个类型的方法?
代码的第一部分是嵌入属性的工作代码
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的所有结构中是多余的$ c
无需初始化
我想更确切的问题是,我想从<$ 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 inNode
and I'm able to callnode.GetString
that's a method onProperties
. The thing I don't like about this is when I initializeNode
I have(?) to initialize theProperties
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 typeProperties
and initializing does not require initializing aProperty
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 hadNode
, I would just have methods forNode
and be done. But because I'll have more thanNode
I find it kind of redundant to add the same methods to all the structs that embedProperties
I guess more to the exact problem, I want to use
Properties
methods fromNode
without having to initializeProperties
.解决方案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 theProperties
methods onNode
, that effect of that syntax is forNode
to take on the memory layout ofProperties
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 typeProperties
notNode
, 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 everyNode
you create.p.s. Hi Jeff!
这篇关于Golang嵌入式结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!