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.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Unveiling Go's Channel: Inside the Runtime’s Concurrency Engine

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

GoRuntimeGoroutineChannelshchan
MaGe Linux Operations
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.