a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 編程 > Golang > 正文

淺談Go Channel 高級實踐

2020-04-01 18:53:42
字體:
來源:轉載
供稿:網友

channel 是 golang 里相當有趣的一個功能,在我使用 golang 編碼的經驗里,大部分事件都會是在享受 channel 和 goroutine 配合的樂趣。所以本文主要介紹 channel 的一些有趣的用法。

這里有 Oling Cat 翻譯的Go編程語言規范里關于 channel(信道)的描述:

信道提供了一種機制,它在兩個并發執行的函數之間進行同步,并通過傳遞(與該信道元素類型相符的)值來進行通信。

這個個描述又乏味、又枯燥。在我第一次閱讀的時候,完全不明白這到底是個什么玩意。事實上,可以認為 channel 是一個管道或者先進先出隊列,非常簡單且輕量。channel 并不是 Golang 首創的。它同樣作為內置功能出現在其他語言中。在大多數情況下,它是一個又大、又笨、又復雜的消息隊列系統的一個功能。

本文主要講實踐,原理部分會一筆帶過,關于 go 語言并發實現和內存模型后續會有文章。

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黄色一级大片在线免费看产 | 黄色网av| 超碰3 | 一区二区三区高清 | 九九热精品视频 | 成人av视 | 国产依人在线 | 亚洲视频在线观看 | 欧美在线视频网站 | 激情婷婷丁香 | 国产91在线视频 | 久久综合九色综合欧美狠狠 | 伊人网在线视频 | 久久国内精品 | 三级视频在线观看 | 亚洲福利一区 | 久久精品播放 | 欧美一级免费大片 | 中文字幕自拍偷拍 | 亚洲人人 | 日日干天天操 | 日韩小视频在线播放 | 青青草视频免费观看 | 一区二区日韩在线观看 | 日韩一级网站 | 丁香婷婷网 | 亚洲国产精品久久久 | 亚洲天堂字幕 | 中国一级特黄毛片大片 | 精品中文字幕一区二区 | 又大又粗又长又黄视频 | 欧美激情精品久久久久久变态 | av一区在线观看 | 成人免费xxxxx在线观看 | 久久国产精品一区二区三区 | 一级毛片免费看 | 国产精品夜夜春夜夜爽久久电影 | aaa久久 | 日韩欧美国产一区二区 | 中文字幕av一区 | 日批的视频 |