Golang併發模型:輕鬆入門select

以前的文章都提到過,Golang的併發模型都來自生活,select也不例外。舉個例子:咱們都知道一句話,「吃飯睡覺打豆豆」,這一句話裏包含了3件事:git

  1. 媽媽喊你吃飯,你去吃飯。
  2. 時間到了,要睡覺。
  3. 沒事作,打豆豆。

在Golang裏,select就是幹這個事的:到吃飯了去吃飯,該睡覺了就睡覺,沒事幹就打豆豆。github

結束髮散,咱們看下select的功能,以及它能作啥。golang

select功能

在多個通道上進行讀或寫操做,讓函數能夠處理多個事情,但1次只處理1個。如下特性也都必須熟記於心:bash

  1. 每次執行select,都會只執行其中1個case或者執行default語句。
  2. 當沒有case或者default能夠執行時,select則阻塞,等待直到有1個case能夠執行。
  3. 當有多個case能夠執行時,則隨機選擇1個case執行。
  4. case後面跟的必須是讀或者寫通道的操做,不然編譯出錯。

select長下面這個樣子,由selectcase組成,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")
    }
}

咱們建立了readChwriteCh2個通道:less

  1. readCh中沒有數據,因此case x := <-readCh讀不到數據,因此這個case不能執行。
  2. writeCh是帶緩衝區的通道,它裏面是空的,能夠寫入1個數據,因此case writeCh <- y能夠執行。
  3. case能夠執行,因此default不會執行。

這個測試的結果是函數

$ go run example.go
Write 1

用打豆豆實踐select

來,咱們看看select怎麼實現打豆豆:eat()函數會啓動1個協程,該協程先睡幾秒,事件不定,而後喊你吃飯,main()函數中的sleep是個定時器,每3秒喊你吃1次飯,select則處理3種狀況:測試

  1. eatCh中讀到數據,表明有人喊我吃飯,我要吃飯了。
  2. sleep.C中讀到數據,表明鬧鐘時間到了,我要睡覺。
  3. 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/...

併發系列文章推薦

  1. 若是這篇文章對你有幫助,請點個贊/喜歡,鼓勵我持續分享,感謝。
  2. 個人文章列表,點此可查看
  3. 若是喜歡本文,隨意轉載,但請保留此原文連接

一塊兒學Golang-分享有料的Go語言技術

相關文章
相關標籤/搜索