MartyMacGyver
MartyMacGyver

Reputation: 10093

How do I efficiently pass a struct allocated in a goroutine back to the main routine via a channel?

At a basic level, I have a main routine that spawns multiple goroutines to process data. Every time a goroutine processes the data it sends back a struct of varying size (it contains slices and/or arrays allocated from within the goroutine each time).

The data isn't huge (say, a few megabytes) but in general is it more efficient (and is it safe) to transfer a pointer to the data versus a copy of it all? If the data structure is static and I transfer a pointer to it, there's a risk that the structure may change while I'm still processing the result of the previous invocation (if it's fully reallocated then perhaps that's not an issue).

Upvotes: 2

Views: 3723

Answers (2)

OneOfOne
OneOfOne

Reputation: 99284

From my understanding you're trying to do something like:

func watchHowISoar() (ch chan *bigData) {
    ch = make(chan *bigData)
    go func() {
        for i := 0; i < 10; i++ {
            bd := &bigData{i}
            ch <- bd
            // as long as you don't modify bd inside this goroutine after sending it, you're safe.
        }
        close(ch)
    }()
    return
}
func main() {
    for iamaleafOnTheWind := range watchHowISoar() {
        fmt.Printf("%p\n", iamaleafOnTheWind)
    }
}

And it is perfectly safe as long as you don't modify the sent data from the sender after you send it.

If you have doubts, try to run it with go run -race main.go, while the race detector isn't perfect, it will usually detect things like that.

Upvotes: 4

Simon Fox
Simon Fox

Reputation: 6425

It's OK and common to send pointers to values. If the value is large, sending a pointer to the value will be more efficient than sending the value. Run a benchmark to find out how large is "large".

The caveat is that you must prevent unsafe concurrent access to the value. Common strategies for preventing unsafe concurrent access are:

  • Pass ownership of the value from the sender to the receiver. The sender does not access the value after sending it. The receiver can do whatever it wants with the value.
  • Treat the value as read only after sending. Neither the sender or receiver modifies the value after sending.

Upvotes: 4

Related Questions