Go關鍵字--select
阿新 • • 發佈:2018-12-10
select
在golang中使用select可以實現一個條件選擇器,select與switch關鍵字有著類似的效果,都是實現了一個條件選擇器,但是select中的判斷條件必須是通訊操作,golang中的通訊操作是 <- 。當通道在操作符左側時,表示向通道中寫入資訊,當通道在操作符右側時,表示讀取通道資訊。
// 寫入操作
通道 <- 值
// 讀取操作
變數 <- 通道
編寫select條件選擇器的語法格式是:
select {
case <- ch1:
// 讀取通道ch1,讀取成功,執行這個分支。
// do something
case val := <- ch2:
// 讀取通道ch2,讀取成功,執行這個分支。
// do something
case ch3 ->:
// 想
// do something
default:
// do something
}
在golang中,支援通訊操作的型別只有chan,所以select中的case條件只能是對chan型別變數的讀寫操作。由於chan型別變數的讀寫操作可能會引起阻塞,為了在使用select選擇器時不陷入阻塞狀態,可以在select程式碼塊中新增default關鍵字,當case條件全部都不滿足時,預設進入default分支,執行完default分支的程式碼後,退出select選擇器。
下邊來一個例子來使用select實現條件選擇。
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("開始時間:", time.Now().Format("2006-01-02 15:04:05"))
select {
case <-time.After(time.Second * 2):
fmt.Println("2秒後的時間:", time.Now().Format("2006-01-02 15:04:05"))
}
}
輸出資訊是:
開始時間: 2017-09-15 23:23:10 2秒後的時間: 2017-09-15 23:23:12
time.After函式返回一個通道型別的變數,然後在case中從這個通道中讀取資訊,如果沒有協程給這個通道傳送資訊,那麼case將會一直阻塞。在呼叫After函式時,傳入了一個時長作為引數,意思是從呼叫After函式算起,到設定的市場後,有協程將會向這個通道傳送一條訊息。當通道收到訊息後,這個case條件滿足,這個case分支下的程式碼將會被執行。
當select中同一時間,有多個case滿足條件時,select會選擇哪一個分支執行,還是執行多個分支呢?答案是:隨機選擇一個滿足滿足條件的case分支執行,這個分支執行完成後,退出select選擇器。請記住:是隨機選擇一個滿足條件的case分支執行。下邊請看示例:
package main
import (
"fmt"
"time"
)
func main() {
var ch1 chan int = make(chan int)
var ch2 chan int = make(chan int)
go func() {
fmt.Println("從通道ch2中讀取資料:", <-ch2)
}()
go func() {
ch1 <- 88
}()
select {
case <-time.After(time.Second * 5):
// do something
fmt.Println("timeout")
case val := <-ch1:
fmt.Println("從通道ch1中讀取資料", val)
// do something
case ch2 <- 99:
// do something
}
time.Sleep(time.Second * 2)
}
輸出資訊有兩種情況,一種是:
從通道ch2中讀取資料: 99
另一種是:
從通道ch1中讀取資料 88