- Code Path:
src/runtime/select.go
IR stage
IR will walk a select statement and generate the code accordingly:
- If there’s no
case, replace the select statement withruntime.block, the current goroutine will be blocked forever. - If there’s only one
case, extract the send or receive operation from thecasestatement. - Otherwise, convert
casevalues to addresses. - If there’s only one
casewith onedefault, replace it with non-block callsselectnbsendorselectnbrecv. - Generate a select statement with the list of
sendandrecvcases, and runselectgoon it. - Run the
caseordefaultbased on the returned index ofselectgo.
selectgo
selectgo takes two major arguments: a list of scase and a list of the orders of recv/send.
It returns the pos of case to execute.
- Build a permuted polling order of cases.
- Build a sorted order of locking (sorted by channel address).
- Lock all channels by the order of locking.
- Iterate through all case channels, and find the goroutines on
waitqorrecvq. If not empty, send/recv immediately.- Closed channels or buffered channels with available slots are also handled during the first round of iteration.
- If there’s a default statement, return immediately with no
caseto run. - Iterate through all case channels, and put the current
gon therecvqorwaitqof each channel. gopartthe currentg.- Once the current
gwakes up, lock all channels, and dequeue from all the channels except the one we’re waking up on.- The
recvstatus is returned bysudog.success
- The
- Return the index and
recvstatus.