- read

Select & For Range Channel: Realizing What You May Not Know

Phuong Le (@func25) 82


Select & For Range Channel: Realizing What You May Not Know

Get a closer look at how ‘select’ and ‘for range’ work with Go channels. This guide highlights less-known behaviors and practical patterns, deepening your understanding of Go concurrency.

Phuong Le (@func25)
Level Up Coding
Published in
7 min read15 hours ago


Photo by Alexander Schimmeck on Unsplash

In our previous discussion, we covered five specific channel types in Go: buffered, unbuffered, directional, nil and closed channels.

If you missed that discussion, it’s important to note that we identified these types to provide a detailed understanding. Yet, at the most basic level, Go channels are primarily either buffered or unbuffered.

Now, we’re focusing on select and for range in Go.

1. Understanding select{}

Basically, the select statement provides a mechanism for a goroutine to wait on multiple channels using the case statement and its main job is to execute the first case that is ready.

select {
case msg1 := <-ch1:
fmt.Println("Received", msg1)
case msg2 := <-ch2:
fmt.Println("Received", msg2)

a. How it works?

In the example above, the select statement waits for either ch1 or ch2 to deliver data. When one of the channels is ready, the corresponding case executes.

“What happens if, by some chance, multiple cases are ready simultaneously?”

That’s where things get interesting, select doesn’t prioritize any case over others, instead, it makes an unbiased, random choice if more than one case is ready.


There’s another aspect to consider, if a default case is included in the select statement and none of the channels are ready, then the select does not wait, it quickly executes the default case:

select {
case msg1 := <-ch1: