Channels
A channel is a typed "pipe" through which goroutines pass values to each other.
The <- operator is used for both sending and receiving.
Unbuffered channel
A send blocks until another goroutine receives the value:
ch := make(chan int)
go func() {
ch <- 42 // send
}()
v := <-ch // receive
fmt.Println(v)
Buffered channel
A send blocks only when the buffer is full:
ch := make(chan string, 2)
ch <- "a"
ch <- "b"
fmt.Println(<-ch, <-ch)
Closing and range
func gen(n int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for i := 0; i < n; i++ {
out <- i
}
}()
return out
}
for v := range gen(5) {
fmt.Println(v)
}
Only the sender should close a channel. Receiving from a closed channel returns
the zero value; you can check the state like this: v, ok := <-ch.
select
select waits until one of several channels is ready:
select {
case msg := <-ch1:
fmt.Println("from ch1:", msg)
case msg := <-ch2:
fmt.Println("from ch2:", msg)
case <-time.After(time.Second):
fmt.Println("timeout")
}
Worker pool
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- j * j
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
for i := 0; i < 5; i++ {
fmt.Println(<-results)
}
}
Directional channels
chan<- T— send-only;<-chan T— receive-only.
This helps the compiler catch mistakes and makes APIs clearer.