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

首頁 > 編程 > Golang > 正文

Golang優雅關閉channel的方法示例

2020-04-01 19:01:45
字體:
來源:轉載
供稿:網友

前言

最近使用go開發后端服務,服務關閉需要保證golang/71577.html">channel中的數據都被讀取完,理由很簡單,在收到系統的中斷信號后,系統需要做收尾工作,保證channel的數據都要被處理掉,然后才可以關閉系統。但實現起來沒那么簡單,下面來一起看看詳細的介紹吧。

關于Go channel設計和規范的批評:

  • 在不能更改channel狀態的情況下,沒有簡單普遍的方式來檢查channel是否已經關閉了
  • 關閉已經關閉的channel會導致panic,所以在closer(關閉者)不知道channel是否已經關閉的情況下去關閉channel是很危險的
  • 發送值到已經關閉的channel會導致panic,所以如果sender(發送者)在不知道channel是否已經關閉的情況下去向channel發送值是很危險的

所以Golang 內建的 close 方法可以關閉 channel,如果往已經關閉的 channel 發送數據,則會報錯:panic: close of closed channel.

看如下代碼,在一段時間內,生產者可以不斷往 channel 寫入數據,消費者進行處理,一段時間后 channel 關閉了,這個時候如果還有數據往 channel 發送,程序就會報錯。

package main import ( "fmt" "sync" "time") func main() { jobs := make(chan int) var wg sync.WaitGroup go func() { time.Sleep(time.Second * 3) close(jobs) }() go func() { for i := 0; ; i++ { jobs <- i fmt.Println("produce:", i) } }() wg.Add(1) go func() { defer wg.Done() for i := range jobs { fmt.Println("consume:", i) } }() wg.Wait()}

多運行幾次出錯的概率會比較大:

produce: 33334consume: 33334consume: 33335produce: 33335produce: 33336consume: 33336consume: 33337produce: 33337produce: 33338consume: 33338consume: 33339produce: 33339produce: 33340consume: 33340panic: send on closed channel goroutine 19 [running]:panic(0x49b660, 0xc042410bb0)  C:/Go/src/runtime/panic.go:500 +0x1afmain.main.func2(0xc04203a180)  C:/Users/tanteng/Go/src/examples/channel_close.go:18 +0x6bcreated by main.main  C:/Users/tanteng/Go/src/examples/channel_close.go:21 +0xb8exit status 2

如何優雅關閉 channel

那么在往通道發數據前如何判斷通道是否關閉呢?

1._,ok := <- jobs

此時如果 channel 關閉,ok 值為 false,如果 channel 沒有關閉,則會漏掉一個 jobs

2.使用 select 方式

再創建一個 channel,叫做 timeout,如果超時往這個 channel 發送 true,在生產者發送數據給 jobs 的 channel,用 select 監聽 timeout,如果超時則關閉 jobs 的 channel.

完整代碼如下:

package main import ( "fmt" "sync" "time") func main() { jobs := make(chan int) timeout := make(chan bool) var wg sync.WaitGroup go func() { time.Sleep(time.Second * 3) timeout <- true }() go func() { for i := 0; ; i++ { select { case <-timeout: close(jobs) return  default: jobs <- i fmt.Println("produce:", i) } } }() wg.Add(1) go func() { defer wg.Done() for i := range jobs { fmt.Println("consume:", i) } }() wg.Wait()}

這樣就可以保證不會往已經關閉的 channel 中發送數據了。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 不卡视频一区 | 国产一区二区三区色淫影院 | 国产一区二区精品在线观看 | 久久9热| 欧美色涩 | 亚洲精品在线免费看 | 久久精品黄| 日韩在线视频免费看 | 欧美久久久| 亚洲日本欧美日韩高观看 | 亚洲精品视频在线观看免费 | 亚洲九九 | 黄页网站免费在线观看 | 久久免费视频3 | 日本在线视频一区二区三区 | 黄色免费观看网站 | 亚洲精品久久久久久久久久久久久 | 狠狠色综合欧美激情 | 亚洲精品乱码久久久久久不卡 | 中文日韩在线 | 国产极品免费 | 国产一级免费视频 | 直接在线观看的三级网址 | 欧美二区在线 | 在线播放av片 | xxxx性欧美 | 日韩成人小视频 | 欧美日韩久久久久 | 欧美一区在线视频 | 国产成人久久 | www国产亚洲精品久久网站 | 成人综合在线观看 | 一区二区三区国产 | 国产精品亚洲第一区在线暖暖韩国 | 欧美激情视频免费观看 | 一区二区在线看 | 艳妇荡乳豪妇荡淫 | 久久激情小视频 | 欧美成人在线免费视频 | 成人免费xxxxx在线视频软件 | 亚洲欧美日韩精品 |