intermediate Step 10 of 15

Channels and Select

Go Programming

Channels and Select

Channels are Go's primary mechanism for communication between goroutines. They provide a typed conduit through which you can send and receive values, enabling safe data sharing without locks. The select statement lets you wait on multiple channel operations simultaneously. Together, goroutines and channels implement Communicating Sequential Processes (CSP), a concurrency model that makes complex concurrent programs easier to reason about and less prone to bugs like deadlocks and race conditions.

Channel Basics

package main

import "fmt"

func main() {
    // Unbuffered channel
    ch := make(chan string)

    go func() {
        ch <- "Hello from goroutine!"
    }()

    msg := <-ch
    fmt.Println(msg)

    // Buffered channel
    jobs := make(chan int, 5)
    for i := 1; i <= 5; i++ {
        jobs <- i
    }
    close(jobs)

    for job := range jobs {
        fmt.Println("Processing job", job)
    }
}

// Worker pool pattern
func workerPool(numWorkers int, jobs <-chan int, results chan<- int) {
    var wg sync.WaitGroup
    for i := 0; i < numWorkers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for job := range jobs {
                results <- job * 2
            }
        }()
    }
    wg.Wait()
    close(results)
}

Select Statement

// Select waits on multiple channels
select {
case msg := <-ch1:
    fmt.Println("From ch1:", msg)
case msg := <-ch2:
    fmt.Println("From ch2:", msg)
case <-time.After(5 * time.Second):
    fmt.Println("Timeout!")
}
Pro tip: Always close channels from the sender side, never the receiver. Use range to receive all values from a channel until it is closed. Use select with time.After() to implement timeouts and prevent goroutines from blocking forever.

Key Takeaways

  • Channels provide typed, safe communication between goroutines.
  • Unbuffered channels synchronize sender and receiver; buffered channels allow asynchronous sends up to capacity.
  • Use select to wait on multiple channels simultaneously.
  • Close channels from the sender; use range to iterate until closed.
  • The worker pool pattern with channels is Go's standard approach to parallel processing.