Implementing Priority in Go's Select Statement
Go's select statement enables goroutines to multiplex on multiple channels, processing data from the channel that becomes ready first. However, it does not natively support prioritizing channels. This article explores a common programming scenario where one desires to prioritize certain channels over others within a select statement.
In the example provided, a goroutine sends data to two channels, out and exit. While both channels are initially empty, the intent is to prioritize out such that all its values are processed before handling exit. Using the standard select statement, as seen in the question, does not achieve this desired behavior.
To address this issue, Go provides an elegant solution. Instead of relying on select's built-in prioritization, the channel that should be prioritized (in this case, exit) should be accessible only to the sender goroutine. When the sender goroutine is ready to terminate, it closes the channel. The receiver goroutine, using a range-based loop to iterate over the channel (for x := range vals), will continue to process data until the channel is closed.
Implementing this solution yields the following code:
package main import ( "fmt" "math/rand" "time" ) var ( produced = 0 processed = 0 ) func produceEndlessly(vals chan int, quit chan bool) { defer close(vals) for { select { case vals <- rand.Int(): produced++ case <-quit: return } } } func quitRandomly(quit chan bool) { d := time.Duration(rand.Int63n(5e9)) fmt.Println("SLEEP", d) time.Sleep(d) fmt.Println("SEND QUIT") quit <- true } func main() { vals, quit := make(chan int, 10), make(chan bool) go produceEndlessly(vals, quit) go quitRandomly(quit) for x := range vals { fmt.Println(x) processed++ time.Sleep(time.Duration(rand.Int63n(5e8))) } fmt.Println("Produced:", produced) fmt.Println("Processed:", processed) }
In this updated code, the quit channel is only communicated from the sender goroutine. This ensures that quit will not be selected until the sender is ready to terminate. Consequently, the receiver goroutine will exhaust all data from vals before handling exit.
The above is the detailed content of How Can I Prioritize Channels in Go's Select Statement?. For more information, please follow other related articles on the PHP Chinese website!