Ever had two friends texting you at the same time, and you had to pick who to reply to first?
That’s basically what Go’s select
statement does — but for channels!
What’s select
?
In Go, channels let goroutines chat.
But what if multiple channels are screaming for attention? select
helps you listen to them non-blockingly (fancy term for “without freezing your code”).
How It Works
Imagine you’re waiting for pizza and a Netflix notification.
With select
, you can react to whichever happens first:
select {
case pizza := <-pizzaChan:
fmt.Println("Pizza’s here! 🍕")
case notification := <-netflixChan:
fmt.Println("New episode! 📺")
}
No pizza? No show? No problem! Add a default
case to avoid waiting forever:
select {
case msg := <-emailChan:
fmt.Println("New email:", msg)
default:
fmt.Println("Still refreshing... 🥱")
}
Testing Select
Let’s write a test to verify our select behavior:
func TestSelect(t *testing.T) {
fastChan := make(chan string)
slowChan := make(chan string)
go func() {
time.Sleep(50 * time.Millisecond)
slowChan <- "slow"
}()
go func() {
fastChan <- "fast"
}()
select {
case msg := <-fastChan:
if msg != "fast" {
t.Errorf("Expected 'fast', got %q", msg)
}
case <-slowChan:
t.Error("Should have received from fastChan first")
case <-time.After(100 * time.Millisecond):
t.Error("Timed out waiting for channels")
}
}
Why It’s Cool
- Multitasking magic: Handle multiple channels at once.
- No deadlocks:
default
keeps your code moving. - Timeouts? Easy: Pair it with
time.After
to bail if things take too long.
Final Tip
Use select
when you’ve got multiple channels and need to prioritize. It’s like a switch statement, but for async awesomeness.
Now go play with it—your goroutines will thank you! 🚀