Go Tutorial · Concurrency · Lesson 24 of 30

Go Channels and select

Send values between goroutines, buffered channels, range over channels and select.

Channels

A channel is a typed pipe between goroutines. ch <- v sends; v := <-ch receives. An unbuffered send waits until someone receives:

Example 1
package main

import "fmt"

func main() {
	ch := make(chan string)
	go func() {
		ch <- "ping"
	}()
	fmt.Println(<-ch)

	nums := make(chan int, 3) // buffered: holds 3 values without a receiver
	for i := 1; i <= 3; i++ {
		nums <- i * 10
	}
	close(nums) // no more values
	for n := range nums {
		fmt.Println(n)
	}
}

Output

ping
10
20
30

Run this on your computer — see “Get Started” for setup.

"Don't communicate by sharing memory; share memory by communicating."

Worker pools

A classic pattern: jobs go into one channel, workers process them, results come out of another:

Example 2
package main

import (
	"fmt"
	"slices"
	"sync"
)

func main() {
	jobs := make(chan int)
	results := make(chan int)
	var wg sync.WaitGroup
	for range 3 { // 3 workers
		wg.Add(1)
		go func() {
			defer wg.Done()
			for n := range jobs {
				results <- n * n
			}
		}()
	}
	go func() {
		for i := 1; i <= 5; i++ {
			jobs <- i
		}
		close(jobs)
	}()
	go func() {
		wg.Wait()
		close(results)
	}()
	var squares []int
	for r := range results {
		squares = append(squares, r)
	}
	slices.Sort(squares) // workers finish in any order
	fmt.Println(squares)
}

Output

[1 4 9 16 25]

Run this on your computer — see “Get Started” for setup.

select

select waits on several channel operations at once — great for timeouts:

Example 3
package main

import (
	"fmt"
	"time"
)

func main() {
	fast := make(chan string)
	go func() {
		time.Sleep(20 * time.Millisecond)
		fast <- "fast result"
	}()
	slow := make(chan string)
	go func() {
		time.Sleep(2 * time.Second)
		slow <- "slow result"
	}()
	for _, ch := range []chan string{fast, slow} {
		select {
		case v := <-ch:
			fmt.Println(v)
		case <-time.After(200 * time.Millisecond):
			fmt.Println("timed out")
		}
	}
}

Output

fast result
timed out

Run this on your computer — see “Get Started” for setup.

Test yourself

What does close(ch) signal?

  1. The channel is deleted
  2. No more values will be sent
  3. Receivers must stop immediately
  4. The buffer is cleared
Show answer

Answer: No more values will be sent