Introduction to Go Channels: Types, Operations, Rules, and Practical Examples

This article explains Go's channel feature, covering its design philosophy, channel types (bidirectional and directional), core operations such as send, receive, close, capacity queries, detailed execution rules for different channel states, and includes several illustrative code examples.

360 Tech Engineering
360 Tech Engineering
360 Tech Engineering
Introduction to Go Channels: Types, Operations, Rules, and Practical Examples

Go provides two fundamental built‑in concurrency primitives—goroutine and channel—and this article focuses on channels, translating and expanding the original Go101 material for easier learning.

Rob Pike famously said, "Do not communicate by sharing memory; instead, share memory by communicating," and channels were created to embody this principle.

A channel is a composite type (like array, slice, map) that carries values of a single element type; it can be nil. Channels can be bidirectional ( chan T) or directional ( chan<- T for send‑only, <-chan T for receive‑only).

Creating a channel uses the built‑in make function, e.g., c := make(chan int, 2), where the optional second argument sets the buffer capacity (default 0 for an unbuffered channel).

Channel operations include:

Closing a channel with close(c) (panic if the channel is nil, already closed, or a send‑only channel).

Sending a value: c <- v (panic if the channel is closed; blocks if the buffer is full).

Receiving a value: v, ok := <-c (ok is false when the channel is closed and empty).

Querying capacity with cap(c) and length with len(c).

The runtime maintains three internal queues for a channel: the receiving‑goroutine queue (RGQ), the sending‑goroutine queue (SGQ), and the value‑buffer queue (VBQ). The interaction of these queues determines whether send/receive operations block or proceed.

Four rule scenarios (A‑D) describe the exact steps the scheduler follows when a goroutine attempts to receive from, send to, or close a channel, covering cases such as empty/non‑empty buffers, nil channels, and closed channels.

Practical examples demonstrate unbuffered and buffered channel usage, a perpetual “football match” simulation using multiple goroutines, and the for‑range loop over a channel, which continues until the channel is closed and its buffer emptied.

All value transfers through a channel involve copying, similar to assignment or function argument passing; large values should be sent via pointers to avoid excessive copying.

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.

BackendconcurrencyGoSynchronizationGoroutineChannel
360 Tech Engineering
Written by

360 Tech Engineering

Official tech channel of 360, building the most professional technology aggregation platform for the brand.

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.