Using select with multiple channels lets your program wait for many things at once and react to whichever happens first.
Select with multiple channels in Go
select {
case val1 := <-chan1:
// handle val1
case val2 := <-chan2:
// handle val2
case chan3 <- val3:
// send val3
default:
// optional: run if no channel is ready
}Each case must be a send or receive operation on a channel.
The default case runs if no other channel is ready, so it prevents blocking.
ch1 or ch2 and prints it.select {
case msg := <-ch1:
fmt.Println("Received from ch1:", msg)
case msg := <-ch2:
fmt.Println("Received from ch2:", msg)
}ch1. If it can't send immediately, runs the default case.select {
case ch1 <- 10:
fmt.Println("Sent 10 to ch1")
default:
fmt.Println("No channel ready to send")
}ch or times out after 1 second.select {
case <-time.After(time.Second):
fmt.Println("Timeout after 1 second")
case msg := <-ch:
fmt.Println("Received:", msg)
}This program creates two channels and sends messages to them after different delays. The select waits for messages from both channels and prints them as they arrive.
package main import ( "fmt" "time" ) func main() { ch1 := make(chan string) ch2 := make(chan string) // Send messages after some time go func() { time.Sleep(2 * time.Second) ch1 <- "hello from ch1" }() go func() { time.Sleep(1 * time.Second) ch2 <- "hello from ch2" }() for i := 0; i < 2; i++ { select { case msg1 := <-ch1: fmt.Println("Received:", msg1) case msg2 := <-ch2: fmt.Println("Received:", msg2) } } }
If multiple channels are ready, select picks one at random.
Use default to avoid blocking if no channels are ready.
Remember to close channels if needed to avoid goroutine leaks.
Select lets you wait on multiple channels at once.
It runs the code for the first channel ready to send or receive.
You can add a default case to do something if no channels are ready.
Practice
What does the select statement do when used with multiple channels in Go?
Solution
Step 1: Understand select behavior
Theselectstatement waits for one of its channel cases to be ready.Step 2: Identify how select chooses a case
It picks one of the channels that is ready to send or receive and runs that case.Final Answer:
It waits until one of the channels is ready to send or receive and executes that case. -> Option AQuick Check:
Select waits for ready channel = A [OK]
- Thinking select runs all channels at once
- Believing select waits for all channels simultaneously
- Assuming select picks channels randomly without readiness check
Which of the following is the correct syntax to use select with two channels ch1 and ch2 for receiving values?
?
Solution
Step 1: Check channel receive syntax
Receiving from a channel usesval := <-chto assign the received value.Step 2: Verify select case syntax
Each case must have a receive operation with assignment likeval := <-ch1.Final Answer:
select { case val := <-ch1: fmt.Println(val) case val := <-ch2: fmt.Println(val) } -> Option DQuick Check:
Correct receive syntax uses := <-channel [OK]
- Using = instead of := for assignment
- Omitting the <- operator for receiving
- Trying to assign channel itself instead of received value
What will be the output of the following Go program?
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(100 * time.Millisecond)
ch1 <- "hello"
}()
go func() {
time.Sleep(50 * time.Millisecond)
ch2 <- "world"
}()
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
}
}Solution
Step 1: Analyze goroutine sleep durations
The goroutine sending toch2sleeps 50ms, andch1sleeps 100ms.Step 2: Determine which channel is ready first
Sincech2sends first, theselectwill receive fromch2and print "world".Final Answer:
world -> Option BQuick Check:
Channel with shorter sleep sends first = world [OK]
- Assuming ch1 sends first because it is listed first
- Expecting both messages to print
- Thinking select waits for all channels
Identify the error in this Go code using select with multiple channels:
package main
import "fmt"
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
select {
case val := <-ch1:
fmt.Println(val)
case val := <-ch2:
fmt.Println(val)
}
}Solution
Step 1: Analyze channel creation
Channelsch1andch2are unbuffered with no goroutines to send values.Step 2: Select behavior without senders
Theselectblocks forever since no channels become ready, causing a deadlock.Final Answer:
The program will deadlock because channels are never written to. -> Option CQuick Check:
No senders + no default = deadlock [OK]
- Thinking channels must be buffered to use select
- Believing select syntax is invalid without a loop
- Assuming a default case is required or invalid
You want to write a Go function that waits on two channels chA and chB and returns the first value received from either. If neither channel is ready immediately, it should return "timeout" after 100 milliseconds. Which select structure correctly implements this?
Solution
Step 1: Use time.After for timeout
Thetime.Afterfunction returns a channel that sends a value after the specified duration, perfect for timeout.Step 2: Check select cases
Cases for receiving fromchAandchBreturn the first received value; the timeout case returns "timeout" after 100ms.Step 3: Validate other options
select { case val := <-chA: return val case val := <-chB: return val default: time.Sleep(100 * time.Millisecond) return "timeout" } uses default with sleep which blocks select; select { case val := <-chA: return val case val := <-chB: return val case <-time.Tick(100 * time.Millisecond): return "timeout" } uses time.Tick which repeats; select { case val := <-chA: return val case val := <-chB: return val case <-time.After(100): return "timeout" } uses incorrect duration type.Final Answer:
select { case val := <-chA: return val case val := <-chB: return val case <-time.After(100 * time.Millisecond): return "timeout" } -> Option AQuick Check:
Use time.After channel for timeout in select [OK]
- Using default with sleep instead of time.After
- Using time.Tick which repeats instead of time.After
- Passing wrong duration type to time.After
Ready to prove it?
Pass the test and this pattern moves unknown
