Go select的用法如下。
Go select可在多個channel的send(發送)或receive(接收)隨機選擇一個來執行。
例如下面建立了兩個channel c1及c2,各以goroutine把值送入,接著用time.Sleep()暫時一秒確保前面的goroutine先於後面的select執行。在for迴圈中用select的case選擇從channel接收資料放入變數s,若沒可執行的channel操作則走default離開迴圈。
package main
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
c1 <- "a"
}()
go func() {
c2 <- "b"
}()
time.Sleep(time.Second)
L:
for {
var s string
select {
case s = <-c1:
case s = <-c2:
default:
break L
}
fmt.Println(s)
}
}
因為select敘述是隨機選擇channel的send或receive操作來執行,所以可能先印出a然後b,也有可能先印出b然後印出a。
select的另一個特性是若選擇的channel操作被阻塞且又沒有default時,則select會等待直到該channel可執行為止。
例如下面select總是先印出b,阻塞一秒才印出a。第一個goroutine中的time.Sleep()等待一秒才發送值給channel c1,所以在第一次迴圈select會先走<-c2;第二次迴圈走<-c1時(因為c2已經空了)由於time.Sleep()值未送入c1,因此select會先阻塞暫停,直到time.Sleep()結束執行c1 <- "a"後select才繼續<-c1。
package main
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(time.Second)
c1 <- "a"
}()
go func() {
c2 <- "b"
}()
for i := 0; i < 2; i++ {
var s string
select {
case s = <-c1:
case s = <-c2:
}
fmt.Println(s)
}
}
沒有留言:
張貼留言