這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
轉載自:http://yanyiwu.com/work/2014/11/08/golang-select-typical-usage.html
golang 的 select 的功能和 select, poll, epoll 相似, 就是監聽 IO 操作,當 IO 操作發生時,觸發相應的動作。
樣本:
ch1 := make (chan int, 1)
ch2 := make (chan int, 1)
…
select {
case <-ch1:
fmt.Println(“ch1 pop one element”)
case <-ch2:
fmt.Println(“ch2 pop one element”)
}
注意到 select 的代碼形式和 switch 非常相似, 不過 select 的 case 裡的動作陳述式只能是【IO 操作】 。
此樣本裡面 select 會一直等待等到某個 case 陳述式完成, 也就是等到成功從 ch1 或者 ch2 中讀到資料。 則 select 語句結束。
【使用 select 實現 timeout 機制】
如下:
timeout := make (chan bool, 1)
go func() {
time.Sleep(1e9) // sleep one second
timeout <- true
}()
ch := make (chan int)
select {
case <- ch:
case <- timeout:
fmt.Println(“timeout!”)
}
當逾時時間到的時候,case2 會操作成功。 所以 select 語句則會退出。 而不是一直阻塞在 ch 的讀取操作上。 從而實現了對 ch 讀取操作的逾時設定。
下面這個更有意思一點。
當 select 語句帶有 default 的時候:
ch1 := make (chan int, 1)
ch2 := make (chan int, 1)
select {
case <-ch1:
fmt.Println(“ch1 pop one element”)
case <-ch2:
fmt.Println(“ch2 pop one element”)
default:
fmt.Println(“default”)
}
此時因為 ch1 和 ch2 都為空白,所以 case1 和 case2 都不會讀取成功。 則 select 執行 default 語句。
就是因為這個 default 特性, 我們可以使用 select 語句來檢測 chan 是否已經滿了。
如下:
ch := make (chan int, 1)
ch <- 1
select {
case ch <- 2:
default:
fmt.Println(“channel is full !”)
}
因為 ch 插入 1 的時候已經滿了, 當 ch 要插入 2 的時候,發現 ch 已經滿了(case1 阻塞住), 則 select 執行 default 語句。 這樣就可以實現對 channel 是否已滿的檢測, 而不是一直等待。
比如我們有一個服務, 當請求進來的時候我們會產生一個 job 扔進 channel, 由其他協程從 channel 中擷取 job 去執行。 但是我們希望當 channel 瞞了的時候, 將該 job 拋棄並回複 【服務繁忙,請稍微再試。】 就可以用 select 實現該需求。
關於記憶體回收
c++ 寫久了的人, 剛接觸 golang 的時候最不能理解的就是為什麼作者要支援記憶體回收。 不管是從記憶體回收行程的實現上看, 還是對於程式員編程習慣的養成方面, 都避免不了編寫出的程式效能損失。 但是寫了幾天 golang 之後, 又覺得有記憶體回收確實大大減輕程式員的心智負擔, 降低編程門檻,提高編程效率。 讓我聯想到 彙編 和 C語言 的關係, 即使 C語言的效能不如彙編寫出來的高, 但是後者還是顛覆了前者。
參考
go語言編程
go語言程式設計
轉載請註明出處: golang的select典型用法