Go Channel 進階實踐

來源:互聯網
上載者:User
  1. 本文主要講實踐,原理部分會一筆帶過,關於 go 語言並發實現和記憶體模型後續會有文章。
  2. channel 實現的源碼不複雜,推薦閱讀,https://github.com/golang/go/blob/master/src/runtime/chan.go

channel 是幹什麼的

意義:channel 是用來通訊的

實際上:(資料拷貝了一份,並通過 channel 傳遞,本質就是個隊列)

channel 應該用在什麼地方

核心:需要通訊的地方

例如以下情境:

  • 通知廣播
  • 交換資料
  • 顯式同步
  • 並發控制
  • ...

記住!channel 不是用來實現鎖機制的,雖然有些地方可以用它來實作類別似讀寫鎖,保護臨界區的功能,但不要這麼用!

channel 用例實現

逾時控制

// 利用 time.After 實現func main() {    done := do()    select {    case <-done:        // logic    case <-time.After(3 * time.Second):        // timeout    }}func do() <-chan struct{} {    done := make(chan struct{})    go func() {        // do something        // ...        done <- struct{}{}    }()    return done}

取最快的結果

比較常見的一個情境是重試,第一個請求在指定逾時時間內沒有返回結果,這時重試第二次,取兩次中最快返回的結果使用。
逾時控制在上面有,下面代碼部分就簡單實現調用多次了。

func main() {    ret := make(chan string, 3)    for i := 0; i < cap(ret); i++ {        go call(ret)    }        fmt.Println(<-ret)}func call(ret chan<- string) {    // do something    // ...    ret <- "result"}

限制最大並發數

// 最大並發數為 2limits := make(chan struct{}, 2)for i := 0; i < 10; i++ {    go func() {        // 緩衝區滿了就會阻塞在這        limits <- struct{}{}        do()        <-limits    }()}

for...range 優先

for ... range c { do } 這種寫法相當於 if _, ok := <-c; ok { do }

func main() {    c := make(chan int, 20)    go func() {        for i := 0; i < 10; i++ {            c <- i        }        close(c)    }()    // 當 c 被關閉後,取完裡面的元素就會跳出迴圈    for x := range c {        fmt.Println(x)    }}

多個 goroutine 同步響應

利用 close 廣播

func main() {    c := make(chan struct{})    for i := 0; i < 5; i++ {        go do(c)    }    close(c)}func do(c <-chan struct{}) {    // 會阻塞直到收到 close    <-c    fmt.Println("hello")}

非阻塞的 select

select 本身是阻塞的,當所有分支都不滿足就會一直阻塞,如果想不阻塞,那麼一個什麼都不乾的 default 分支是最好的選擇

select {case <-done:    returndefault:   }

for{select{}} 終止

盡量不要用 break label 形式,而是把終止迴圈的條件放到 for 條件裡來實現

for ok {    select {    case ch <- 0:    case <-done:        ok = false    }}

未完待續

...

channel 特性

基礎特性

操作 值為 nil 的 channel 被關閉的 channel 正常的 channel
close panic panic 成功關閉
c<- 永遠阻塞 panic 阻塞或成功發送
<-c 永遠阻塞 永遠不阻塞 阻塞或成功接收

happens-before 特性

  1. 無緩衝時,接收 happens-before 發送
  2. 任何情況下,發送 happens-before 接收
  3. close happens-before 接收

參考

  • https://go101.org/article/channel.html
  • https://golang.org/doc/effective_go.html#channels
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.