Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would you want to use composition in golang?

Tags:

go

In the following code I show what I think is the difference between embedding (where methods get promoted) and composition (where methods are not promoted) in golang.

Why would you ever want to use composition in golang?

type obj1Inherited struct {
    obj2
}

type obj1Composed struct {
    someobj obj2
}

type obj2 struct {
}

func (o obj2) printTest() {
    fmt.Println("obj2")
}

func main() {
    o := obj1Inherited{}
    o.printTest() //fine - printTest is promoted

    obj1Composed := obj1Composed{}
    obj1Composed.someobj.printTest() //fine because I'm using the composed obj
    obj1Composed.printTest() //not fine - printTest is NOT promoted
like image 709
Charlie Avatar asked Apr 18 '16 21:04

Charlie


People also ask

Why do we need interface in Golang?

Interfaces allow us to not repeat code. We can use interfaces to pass multiple structs into the same function where we want the same behavior.

Why there is no inheritance in Golang?

Since Golang does not support classes, so inheritance takes place through struct embedding. We cannot directly extend structs but rather use a concept called composition where the struct is used to form other objects. So, you can say there is No Inheritance Concept in Golang.

Does Go support inheritance or generic?

Go does not support inheritance, however, it does support composition. The generic definition of composition is "put together".

How do I compare structs in Golang?

In Go language, you are allowed to compare two structures if they are of the same type and contain the same fields values with the help of == operator or DeeplyEqual() Method.


1 Answers

It is worth going over the section on Embedding in Effective Go.

A common example is having a struct/map with a Mutex.

type SafeStruct struct {
    SomeField string 
    *sync.Mutex
}

It is much easier to type

safe := SafeStruct{SomeField: "init value"}

safe.Lock()
defer safe.Unlock()
safe.SomeField = "new value"

than having to either write appropriate wrapper functions (which are repetitive) or have the stutter of

safe.mutex.Unlock()

when the only thing you would ever do with the mutex field is access the methods (Lock() and Unlock() in this case)

This becomes even more helpful when you are trying to use multiple functions on the embedded field (that implemement an interface like io.ReadWriter).

like image 142
matt.s Avatar answered Oct 07 '22 14:10

matt.s