Go

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 -race reports 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 with channel 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{}. With chan struct{} the runtime allocates no buffer memory for elements, only the hchan header.

More on Channels & select

All 38 Channels & select questions