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
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.
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.
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.
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.
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
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!
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With