Lesson 15 / 26
Channels and Pipelines
Communicate by sending values.
Unbuffered, buffered, closed
A channel passes values between goroutines. An unbuffered channel synchronises sender and receiver; a buffered channel (make(chan T, n)) lets sends proceed until the buffer is full. The sender closes a channel to signal no more values, and for v := range ch stops when it is closed. Directional types (<-chan T, chan<- T) document who sends and who receives. Chaining stages through channels builds pipelines.
A two-stage pipeline and a buffered channel, run
I ran this with Go 1.27.1 (go run . in a module named demo, standard library only). A producer sends 1 to 5, a square stage squares them, and main sums them to 55. The buffered channel holds two values without a receiver, then both are read.
package main
import "fmt"
func producer(n int) <-chan int {
ch := make(chan int)
go func() {
defer close(ch) // closing tells receivers no more values are coming
for i := 1; i <= n; i++ {
ch <- i
}
}()
return ch
}
func square(in <-chan int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for v := range in {
out <- v * v
}
}()
return out
}
func main() {
sum := 0
for v := range square(producer(5)) { // pipeline: producer -> square -> main
sum += v
}
fmt.Println("sum of squares 1..5 =", sum)
buf := make(chan string, 2) // buffered: sends do not block until full
buf <- "a"
buf <- "b"
fmt.Println(len(buf), cap(buf), <-buf, <-buf)
}
Output:
sum of squares 1..5 = 55 2 2 a b
Only the sender closes
Closing from the receiving side, or closing twice, panics; give ownership of closing to the sender.
Quick check: What ends a for v := range ch loop?
- The channel being closed and drained
- Receiving a zero value
- A timeout by default
- The buffer becoming full
Answer
The channel being closed and drained — Close signals completion.