Built-in Golang Structure

Is it possible to inherit type methods without using inline structures?

The first piece of code is the working code that embeds the Property structure in Node , and I can call node.GetString , which is a method on Properties . I don't like this when I initialize the Node . I have (?) To initialize the Properties structure inside it. Is there any 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 initialization does not require initialization of the Property structure. The following code does not work, but it can be clear what my purpose 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 will add more structures that will use the methods of Properties , so I ask. If I had only Node , I would only have methods for Node and executed. But since I will have more than Node , I find it unnecessary to add the same methods to all structures that insert Properties

I think more for a specific problem, I want to use Properties methods from Node without initializing Properties .

+6
source share
2 answers

So, you are faced with the features of Go here. Embedding is the only way that methods of one structure can "advance" to exist on another structure. Although it feels intuitive that type Node Properties should expose Properties methods to Node , this effect of this syntax for Node should occupy the Properties memory layout, but not any of its methods.

This does not explain why this design was chosen, but Go Spec is at least defined if it is dry. If you read it exactly as it appears, without interpretation, it is very accurate:

A set of methods such as an interface is its interface. A collection of methods of any other type T consists of all declared methods with a receiver type T

GetString has a receiver like Properties not Node , which seriously interprets the specification as if you were an accountant, without imagination. Said:

Additional rules apply to structures containing anonymous fields, as described in the section on structure types.

...

A field or method f of an anonymous field in structure x is called promoted if xf is the legal selector that designates this field or method f.

Promoted fields act like regular structure fields, except that they cannot be used as field names in compound structure literals.

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

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

This line about compound literals is what makes you declare Properties inside every Node created.

ps Hello Jeff!

+3
source

The short answer to your last question is simply No.

There is a big difference between a type declaration and an attachment in golang , you can do your last example by manually performing type conversion between Node and Properties :

 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(Properties(*singleNode).GetString("test")) // :D } 

But this is clearly not what you want, you need to structure with syntax of type aliases, which is impossible in , I think you should stick to your first approach and ignore the fact that the code is redundant and ugly.

+1
source

All Articles