Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a pointer receiver in a goroutine

I have a method with a pointer receiver, I was wondering if using this pointer receiver is safe to use inside a goroutine within this method? or should I pass this pointer receiver as a parameter?

for example:

func (m *dummyStruct) doSomething {
    /* do a bunch of stuff */
    go func() {
        m.a = x
        m.doSomethingElse()
    }()
    return y
}

I know that I can not go wrong by passing m as a parameter to the goroutine but I was wondering if it is extremely necessary

like image 930
Keeto Avatar asked Sep 16 '16 18:09

Keeto


People also ask

When would you use a pointer receiver?

There are two reasons to use a pointer receiver. The first is so that the method can modify the value that its receiver points to. The second is to avoid copying the value on each method call. This can be more efficient if the receiver is a large struct, for example.

What is the difference between a pointer receiver and a value receiver?

Pointer receiver passes the address of a type to the function. The function stack has a reference to the original object. So any modifications on the passed object will modify the original object. This shows that the method with value receivers modifies a copy of an object, And the original object remains unchanged.

Is it possible to call methods that are declared with a value receiver using a pointer in Golang?

you can mix and match methods with value receivers and methods with pointer receivers, and use them with variables containing values and pointers, without worrying about which is which. Both will work, and the syntax is the same.

Can a Goroutine start a Goroutine?

It's perfectly acceptable to call a goroutine from another goroutine. The calling goroutine will still exit and the new goroutine will go on it's merry way. Show activity on this post. Spaning a new goroutine from within a goroutine is per se perfectly fine.


3 Answers

If you are modifying state of m, you'll need a mutex lock and careful locking patterns.

Other than that, this will increase context switching across your thread boundries under most circumstances.

This is why we have the Go idiom:

Do not communicate by sharing memory; instead, share memory by communicating.

https://blog.golang.org/share-memory-by-communicating

like image 149
eduncan911 Avatar answered Oct 18 '22 19:10

eduncan911


I'd seen the link @eduncan911 posted but never tried to apply it. Hopefully this example helps:

package main

import (
    "fmt"
    "time"
)

type dummyStruct struct {
    a int
}

func (m *dummyStruct) doSomethingElse() {
    fmt.Println(m.a)
}

func doSomething(c chan int) {
    for i := 0; i < 5; i++ {
        go func() {
            x := time.Now().Unix()
            c <- int(x)
        }()
        time.Sleep(time.Second)
    }
}

func main() {
    outputs := make(chan int)
    m := &dummyStruct{}
    doSomething(outputs)
    for {
        //block until we can read from channel:
        x := <-outputs
        m.a = x
        m.doSomethingElse()
    }
}

//Output:
go run main.go
1474052448
1474052449
1474052450
1474052451
1474052452
fatal error: all goroutines are asleep - deadlock!
like image 43
Plato Avatar answered Oct 18 '22 20:10

Plato


I think Pointer is not the right way to share data with respect to goroutines, as it will decrease the performance. The best option is channels.

like image 3
ganesh kumar Avatar answered Oct 18 '22 18:10

ganesh kumar