select is a powerful Go construct for working with channels. It allows you to wait for data to arrive from multiple channels or for their closure. As soon as one of the cases is ready, the corresponding branch is executed, while the others are ignored in the current iteration.
ch1 := make(chan int) ch2 := make(chan string) go func() { ch1 <- 42 }() go func() { ch2 <- "hello" }() select { case i := <-ch1: fmt.Println("received from ch1:", i) case s := <-ch2: fmt.Println("received from ch2:", s) default: fmt.Println("no communication") }
Subtleties:
What happens if no channel is ready for reading/writing in select and the default block is absent?
Answer: Select will block until one of the channels is ready for operation.
Story
A developer implemented a data stream interruption function through select without a default block, assuming that the function would "release control" after several attempts. The channels remained empty, and the function got permanently blocked in select, causing the data streams of the microservice to hang.
Story
Select was used with multiple channels, and some goroutines experienced panics when channels were closed, which led to leaks and crashes. There was no check for channel closure (through the ok variable).
Story
In one of the projects, developers added a default block in select to avoid blocking. However, this led to a busy loop — select was executed in a loop, the default was triggered immediately, and the CPU was loaded at 100% instead of waiting for events from the channels.