Lab 02: Select Statement

Time: 30 minutes | Level: Practitioner | Docker: docker run -it --rm golang:1.22-alpine sh

Overview

select lets a goroutine wait on multiple channel operations simultaneously. It is to channels what switch is to values — but non-deterministic when multiple cases are ready. It is the cornerstone of timeouts, cancellations, and fan-in merging.

Step 1: Basic Select with Multiple Channels

select picks whichever case is ready. If multiple are ready, it chooses randomly.

package main

import "fmt"

func main() {
    ch1 := make(chan string, 1)
    ch2 := make(chan string, 1)
    ch1 <- "one"
    ch2 <- "two"

    for i := 0; i < 2; i++ {
        select {
        case msg := <-ch1:
            fmt.Println("from ch1:", msg)
        case msg := <-ch2:
            fmt.Println("from ch2:", msg)
        }
    }
}

💡 Tip: When both channels have data, select picks randomly — this is by design for fairness.

Step 2: Default Case (Non-blocking)

A default case executes immediately if no other case is ready, making the select non-blocking.

Step 3: Timeout with time.After

time.After(d) returns a channel that receives a value after duration d — perfect for select timeouts.

💡 Tip: time.After leaks the underlying timer until it fires. For tight loops, use time.NewTimer and call timer.Stop().

Step 4: Done Channel Pattern

A done channel signals goroutines to stop work — the original cancellation pattern before context.

Step 5: context.WithTimeout

context is the idiomatic way to propagate deadlines and cancellations through call chains.

Step 6: Select in a Loop (Heartbeat Pattern)

Step 7: Multiplex with Fan-In Using Select

Step 8: Capstone — Rate-Limited Worker

Combine select, ticker, done channel, and context for a rate-limited job processor.

📸 Verified Output:

Summary

Concept
Key Points

select

Waits on multiple channel ops; random when multiple ready

default

Makes select non-blocking

time.After

Simple per-operation timeout

time.NewTimer

Reusable timer; call .Stop() to avoid leak

Done channel

close(done) broadcasts cancellation to all waiters

context.WithTimeout

Idiomatic cancellation with deadline propagation

context.WithCancel

Manual cancellation via cancel() function

Nil channel

A nil channel in select is always skipped — useful for disabling cases

Last updated