Skip to content
Channels
step 1/5

Reading — step 1 of 5

Learn

~3 min readGoroutines and Channels

Channels

A channel is a typed conduit between goroutines: one side sends values in, the other receives them out, and the runtime handles every bit of the synchronization. Channels are how Go programs move both data and ownership between concurrent parts.

go

Blocking is the feature

On an unbuffered channel a send blocks until a receiver is ready, and vice versa — the two goroutines meet. That rendezvous is the synchronization: when your send completes, you know the other side has the value. A buffered channel decouples the two sides by up to cap values; sends block only when the buffer is full.

If every goroutine ends up blocked, the runtime kills the program with fatal error: all goroutines are asleep - deadlock! — you will meet this message the first time you forget a close.

close: how receivers learn it is over

go

close is a one-way signal from the sender meaning "no more values." After the channel drains, receives return the zero value with ok == false, and — most usefully — range exits:

go

Three things panic: sending on a closed channel, closing a channel twice, closing a nil channel. Hence the ownership idiom: only the sender closes, and defer close(ch) at the top of the sending goroutine makes that happen on every exit path.

Direction in the type

Function signatures can restrict a channel to one direction:

go

Misusing the channel becomes a compile error — the cheapest bug report you will ever get.

Pipelines

Chaining stages with channels is the canonical Go pattern: each stage receives, transforms, and sends onward.

go

When the producer closes its channel, the next stage's range ends, its defer close fires, and the shutdown ripples cleanly down the whole pipeline. (Waiting on several channels at once needs select — that is lesson 5.1.)

Your exercise

Exactly this pipeline: a producer goroutine sends each input int into a; a squarer goroutine ranges over a and sends n * n into b; main sums what arrives on b. The starter already has both goroutines and both defer close lines — you fill in the two sends.

Mistakes the grader will catch:

  1. Forgetting to square. Fill the second TODO with b <- n and input 1 2 3 4 5 prints 15; the expected output is 55 (1+4+9+16+25).
  2. Leaving a TODO as _ = n. Nothing is ever sent; the channels just close, and you print 0.
  3. Removing a defer close. The downstream range never terminates: fatal error: all goroutines are asleep - deadlock! instead of output.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…