Unveiling Go's Channel: Inside the Runtime’s Concurrency Engine
This article dives deep into Go's channel implementation, explaining the hchan data structure, how make creates channels, the send/receive mechanics, goroutine scheduling, blocking behavior, and provides practical code examples to illustrate these concepts.
Go's channel underlying data structure is the hchan struct, defined in src/runtime/chan.go. This article explains how channels are created with make, how they enable CSP‑style communication, and how the runtime scheduler coordinates goroutine execution.
Using a simple task‑queue example, we create a buffered channel and launch a fixed number of workers:
func main() {
// buffered channel
ch := make(chan Task, 3)
// start workers
for i := 0; i < numWorkers; i++ {
go worker(ch)
}
// send tasks to workers
hellaTasks := getTaks()
for _, task := range hellaTasks {
ch <- task
}
// ...
}
func worker(ch chan Task) {
for {
// receive task
task := <- ch
process(task)
}
}The channel provides four key properties: goroutine safety, FIFO semantics (buffered channels), and automatic blocking/unblocking of goroutines.
make chan
When make creates a channel, it allocates an hchan struct on the heap. The struct looks like this:
type hchan struct {
qcount uint // total data in the queue
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // points to an array of dataqsiz elements
elemsize uint16
closed uint32
elemtype *_type
sendx uint // send index
recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
lock mutex
}The make call allocates memory for this struct and returns a pointer, so the channel variable itself is a pointer shared across functions.
The hchan uses a circular queue ( buf) to store data and two wait‑queues ( sendq and recvq) to track blocked senders and receivers, protected by a mutex.
Sending and Receiving
Sending and receiving involve the four main fields of hchan. In the task‑queue example, G1 sends tasks while G2 receives them. When the buffer is empty, the sender copies data into buf and increments sendx; the receiver copies data out of buf and increments recvx. No memory is shared directly; communication occurs via copies, matching the CSP model.
Do not communicate by sharing memory; instead, share memory by communicating.
If the buffer becomes full, the sending goroutine blocks. The runtime marks the goroutine as waiting, removes it from its OS thread, and schedules another runnable goroutine.
Goroutine Pause/Resume
Goroutine scheduling uses three runtime structures: M (OS thread), P (processor context), and G (goroutine). Each M holds a P, which maintains a run‑queue of goroutines.
When a sender blocks, the runtime creates a sudog representing that goroutine and places it on sendq. The sudog stores pointers to the channel and the data to be sent.
type waitq struct {
first *sudog
last *sudog
}When a receiver later reads from the channel, the runtime wakes the blocked sender, moves it back to the run‑queue, and the data is copied directly from the sender’s buffer to the receiver’s variable.
Waiting on an Empty Channel
If a receiver runs first on an empty channel, it blocks and a sudog is placed on recvq. When a sender later provides data, the runtime copies the data directly into the receiver’s memory without locking the channel buffer.
Conclusion
Go’s built‑in concurrency model, powered by goroutines and channels, implements the CSP paradigm efficiently. Understanding the underlying hchan structure and the runtime’s scheduling mechanisms helps developers write high‑performance concurrent programs and troubleshoot blocking behavior.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
