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)
}
}
沒有留言:
張貼留言