What exactly gets copied when you send on a channel, and what limits apply to element types and buffer sizes?
Question 220HardGo 1.22 to 1.25
A send copies the value (elemsize bytes) into the buffer or straight to the receiver. That means:
- A large struct is copied on every send and again on every receive. For big payloads, send a pointer instead.
- Slices, maps, pointers and structs holding them copy only the header or pointer, so the backing data is shared. The convention is that sending transfers ownership. If the sender changes the data after sending, that is a data race, and
go test -racereports it.
buf := make([]byte, 0, 1024)
for _, rec := range records {
buf = append(buf[:0], rec...)
out <- buf // BUG: every receiver sees the same backing array, overwritten next iteration
}
// Fix: out <- bytes.Clone(buf) (or allocate a new slice per send)
Limits:
- The element type must be smaller than 64 KiB.
make(chan [1 << 16]byte)fails to compile withchannel element type too large (>64kB). - A negative constant buffer size is a compile error. A negative or too large runtime size panics with
makechan: size out of range. - Any type can be an element type, including interfaces, functions, other channels, and zero-size types like
struct{}. Withchan struct{}the runtime allocates no buffer memory for elements, only thehchanheader.
More on Channels & select
- Q218What happens to goroutines that are already blocked on a channel when it is closed?
- Q219Go has no unbounded channels. Why not, and how would you build one?