Golang: Assign Type to Another Structure

So, I have this example: Go to the site

package main import ( "fmt" ) type Circle struct{} func (c Circle) Something() { fmt.Println("something") } type Rectangle struct { Circle } func (a Rectangle) SomethingElse() { fmt.Println("SomethingElse") } type Form Rectangle func main() { c := Form{} c.Circle.Something() c.SomethingElse() } 

I don’t understand why I can call Something from the built-in Circle , but I can not call Somethingelse from the Rectangle in the Form type. Also, I don’t understand what benefit I get when I declare a type of some other type, for example, here in Form .

+5
source share
3 answers

It:

 type Form Rectangle 

Creates a new type named Form that has a Rectangle as its base type.

This means that the Rectangle fields (which is the structure) will be defined for the Form .

But methods are tied to a specific type. When you create a new type ( Form ), this new type will not have any methods of its base type, so you cannot call c.SomethingElse() , because SomethingElse() is a method of type Rectangle .

c.Circle.Something() works because c.Circle is a field of type Circle , and Something() is a method of type Circle .

If you want to call the Rectangle.SomethingElse() method, which requires a value of type Rectangle (receiver type Rectangle ). Since the base type of Form is Rectangle , you can simply get a value of type Rectangle from a value of type Form using a simple conversion type:

 Rectangle(c).SomethingElse() // This works 

The advantage of creating a new type is that you can create / add to it your own methods. A common example is the implementation of the sort.Interface interface. Say you have a piece of something, for example. []Rectangle or fragment of some type that you do not control (because it is part of another package, and methods for the type can be defined in only one package). If you want to sort this fragment, you create a new type for which you can define methods, sort.Interface methods, for example:

 type SortRectangle []Rectangle func (s SortRectangle) Len() int { return len(s) } func (s SortRectangle) Less(i, j int) bool { return s[i] <some-logic> s[j] } func (s SortRectangle) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 

The function sort.Sort() is able to sort any value that implements sort.Interface . []Rectangle There is no []Rectangle , but we just created a new type of SortRectangle . And if we have a value of type []Rectangle , we can convert it to SortRectangle , since the former is the base type of the latter, and after doing the conversion, we have a value of type SortRectangle that can be passed to sort.Sort() to sort it :

 rs := []Rectangle{} // Sort rs: sort.Sort(SortRectangle(rs)) 

Please note that a conversion like the above SortRectangle(rs) only changes the runtime type information, it does not change the memory representation of rs , therefore it is safe and efficient.

If you want the new type to have methods of the "old" type, then use the attachment. See Ainar-G Answer. In fact, you already did this by inserting a Circle into a Rectangle : the Rectangle type has a Something() method, because Something() is a Circle method:

 Rectangle{}.Something() // Prints "something" 
+8
source

A simple rule in Go. If you want to use type methods, do

 type A struct { B } 

and if you don’t need type methods, do

 type AB 

Why do we need a second form? Interfaces, for example. Sometimes we do not want the value to satisfy the interface, for example here . In other cases, you only need types, not their methods.

Go gives you the opportunity to get the same type, but with an empty set of methods.

+3
source

The whole (and only) reason to make type Form Rectangle is to define a new type with different methods. In your example: no methods. c is a form and has no methods, only raison d'être does not have a SomethingElse() method.

But a Form still inserts a circle accessible as c.Circle and which is Circle , so it explicitly has a Something() method.

+1
source

Source: https://habr.com/ru/post/1258768/


All Articles