以前的文章都提到過,Golang的併發模型都來自生活,select也不例外。舉個例子:咱們都知道一句話,「吃飯睡覺打豆豆」,這一句話裏包含了3件事:git
在Golang裏,select就是幹這個事的:到吃飯了去吃飯,該睡覺了就睡覺,沒事幹就打豆豆。github
結束髮散,咱們看下select的功能,以及它能作啥。golang
在多個通道上進行讀或寫操做,讓函數能夠處理多個事情,但1次只處理1個。如下特性也都必須熟記於心:bash
case
後面跟的必須是讀或者寫通道的操做,不然編譯出錯。select長下面這個樣子,由select
和case
組成,default
不是必須的,若是沒其餘事可作,能夠省略default
。併發
func main() { readCh := make(chan int, 1) writeCh := make(chan int, 1) y := 1 select { case x := <-readCh: fmt.Printf("Read %d\n", x) case writeCh <- y: fmt.Printf("Write %d\n", y) default: fmt.Println("Do what you want") } }
咱們建立了readCh
和writeCh
2個通道:less
readCh
中沒有數據,因此case x := <-readCh
讀不到數據,因此這個case不能執行。writeCh
是帶緩衝區的通道,它裏面是空的,能夠寫入1個數據,因此case writeCh <- y
能夠執行。case
能夠執行,因此default
不會執行。這個測試的結果是函數
$ go run example.go Write 1
來,咱們看看select怎麼實現打豆豆:eat()
函數會啓動1個協程,該協程先睡幾秒,事件不定,而後喊你吃飯,main()
函數中的sleep
是個定時器,每3秒喊你吃1次飯,select
則處理3種狀況:測試
eatCh
中讀到數據,表明有人喊我吃飯,我要吃飯了。sleep.C
中讀到數據,表明鬧鐘時間到了,我要睡覺。default
是,沒人喊我吃飯,也不到時間睡覺,我就打豆豆。import ( "fmt" "time" "math/rand" ) func eat() chan string { out := make(chan string) go func (){ rand.Seed(time.Now().UnixNano()) time.Sleep(time.Duration(rand.Intn(5)) * time.Second) out <- "Mom call you eating" close(out) }() return out } func main() { eatCh := eat() sleep := time.NewTimer(time.Second * 3) select { case s := <-eatCh: fmt.Println(s) case <- sleep.C: fmt.Println("Time to sleep") default: fmt.Println("Beat DouDou") } }
因爲前2個case都要等待一會,因此都不能執行,因此執行default
,運行結果一直是打豆豆:spa
$ go run x.go Beat DouDou
如今咱們不打豆豆了,你把default
和下面的打印註釋掉,多運行幾回,有時候會吃飯,有時候會睡覺,好比這樣:code
$ go run x.go Mom call you eating $ go run x.go Time to sleep $ go run x.go Time to sleep
select很簡單但功能很強大,它讓golang的併發功能變的更強大。這篇文章寫的囉嗦了點,重點是爲下一篇文章作鋪墊,下一篇咱們將介紹下select的高級用法。
select的應用場景不少,讓我總結一下,放在下一篇文章中吧。
可在Github查看:https://github.com/Shitaibin/...
- 若是這篇文章對你有幫助,請點個贊/喜歡,鼓勵我持續分享,感謝。
- 個人文章列表,點此可查看
- 若是喜歡本文,隨意轉載,但請保留此原文連接。