Describe the runtime internals of a channel (hchan).
A channel value is a pointer to a runtime.hchan struct allocated on the heap. Its main fields are:
qcount,dataqsiz: number of elements currently queued and buffer capacity.buf: pointer to a circular array ofdataqsizelements, withsendx/recvxindices.elemsize,elemtype: used to copy values in and out.closed: flag.recvq,sendq: FIFO linked lists (waitq) ofsudogs, one per parked goroutine.lock: a runtime mutex that protects all of the above.
On a send, the runtime takes the lock. If a receiver is waiting in recvq, it copies the value directly onto that goroutine's stack, skipping the buffer, and marks the goroutine runnable. Otherwise, if the buffer has room, it copies into buf[sendx]. If neither is possible, it enqueues a sudog on sendq and parks the goroutine with gopark. Receive mirrors this. When the buffer is full and a sender is waiting, a receiver takes the head of the buffer and moves the waiting sender's value into the freed slot, which keeps FIFO order.
Gotchas: since a channel is a pointer, passing it by value is cheap and every copy shares the same state. Operations are mutex-protected, not lock-free, so a heavily contended channel can cost more than a sync.Mutex or atomics.
More on Channels & select
- Q183What is the difference between buffered and unbuffered channels in terms of synchronization semantics?
- Q185Give the complete table of channel operation behavior for nil, open, and closed channels.
- Q186What does this print? (receiving from a closed buffered channel)
- Q187Explain the comma-ok idiom on channel receive. When is it needed and when is
for rangebetter? - Q188Who should close a channel, and why? What are the rules?
- Q189How do you safely close a channel that might be closed by multiple goroutines?