7. Select
Sometimes we have a single goroutine listening to multiple channels and want to process data in the order it comes through each channel.
A select statement is used to listen to multiple channels at the same time. It is similar to a switch statement but for channels.
select {
case i, ok := <-chInts:
if ok {
fmt.Println(i)
}
case s, ok := <-chStrings:
if ok {
fmt.Println(s)
}
}The first channel with a value ready to be received will fire and its body will execute. If multiple channels are ready at the same time then one is chosen randomly. In the example above, the ok variable is a boolean. It is true while the channel is open, and false when the channel is closed by the sender.
Assignment
Complete the logMessages function.
Use an infinite for loop and a select statement to log the emails and sms messages as they come in order across the two channels. Add a condition to return from the function when one of the two channels closes, whichever is first.
Use the logSms and logEmail functions to log the messages.
Solution
What it does, in plain terms:
selectwaits until eitherchSmsorchEmailshas a value ready.When one is ready, it receives it and logs it immediately (
logSms/logEmail).If a receive returns
ok == false, that channel is closed → youreturnand stop (per “whichever closes first”).
Closed-channel behavior: once a channel is closed, receiving from it is always immediately ready (it returns the zero value + ok=false). That means if you didn't return, your select would keep picking the closed channel over and over. Returning avoids that problem.
Non-deterministic order: if both channels happen to have a value ready at the same time, Go chooses one case “randomly”. So you'll get “arrival order” in the practical sense, but ties aren't stable.