Go

How does select choose among multiple ready cases? Is it fair?

Question 190MediumGo 1.22 to 1.25

If more than one case is ready, select picks one uniformly at random (pseudo-random). Source order gives no priority. The runtime (selectgo) shuffles the poll order with cheaprand and locks the channels in address order to avoid deadlocks between concurrent selects. If no case is ready and there is a default, the default runs. Otherwise the goroutine parks on every channel at once and wakes on whichever becomes ready first.

The randomness prevents starvation: a constantly busy first case can't shut out the others. It also means that you can't rely on case order for priority.

// Common bug: expecting quit to "win"
for {
	select {
	case v := <-data:  // may keep getting picked even after quit is closed
		handle(v)
	case <-quit:
		return
	}
}

If both are ready, each iteration has a 50% chance of processing another data item. That is usually fine, but when you need strict "stop now" behavior, add a priority check (see the next question). Also, all channel and value expressions in every case are evaluated once, in source order, on entry to select, before a case is chosen.

More on Channels & select

All 38 Channels & select questions