Everton
Everton

Reputation: 13845

Is a struct actually copied between goroutines if sent over a Golang channel?

If a large struct is sent over a channel in Go, is it actually copied between goroutines?

For example, in the code below, will Go actually copy all largeStruct data between goroutines producer and consumer?

package main

import (
    "fmt"
    "sync"
)

type largeStruct struct {
    buf [10000]int
}

func main() {
    ch := make(chan largeStruct)
    wg := &sync.WaitGroup{}
    wg.Add(2)
    go consumer(wg, ch)
    go producer(wg, ch)
    wg.Wait()
}

func producer(wg *sync.WaitGroup, output chan<- largeStruct) {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        fmt.Printf("producer: %d\n", i)
        output <- largeStruct{}
    }
    close(output)
}

func consumer(wg *sync.WaitGroup, input <-chan largeStruct) {
    defer wg.Done()
    i := 0
LOOP:
    for {
        select {
        case _, ok := <-input:
            if !ok {
                break LOOP
            }
            fmt.Printf("consumer: %d\n", i)
            i++
        }
    }
}

Playground: http://play.golang.org/p/fawEQnSDwB

Upvotes: 21

Views: 10951

Answers (2)

OneOfOne
OneOfOne

Reputation: 99284

Yes, everything is a copy in Go, you can easily work around that by changing the channel to use a pointer (aka chan *largeStruct).

// demo: http://play.golang.org/p/CANxwt8s2B

As you can see, the pointer to v.buf is different in each case, however if you change it to chan *largeStruct, the pointers will be the same.

@LucasJones provided a little easier to follow example: https://play.golang.org/p/-VFWCgOnh0

As @nos pointed out, there's a potential race if you modify the value in both goroutines after sending it.

Upvotes: 25

peterSO
peterSO

Reputation: 166616

The Go Programming Language Specification

Send statements

A send statement sends a value on a channel. The channel expression must be of channel type, the channel direction must permit send operations, and the type of the value to be sent must be assignable to the channel's element type.

It's a copy because the value is sent to the channel by assignment to the channel's element type. If the value is a struct, then the struct is copied. If the value is a pointer to a struct, then the pointer to the struct is copied.

Upvotes: 8

Related Questions