使用Golang怎么關閉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: 33334 consume: 33334 consume: 33335 produce: 33335 produce: 33336 consume: 33336 consume: 33337 produce: 33337 produce: 33338 consume: 33338 consume: 33339 produce: 33339 produce: 33340 consume: 33340 panic: send on closed channel goroutine 19 [running]: panic(0x49b660, 0xc042410bb0) C:/Go/src/runtime/panic.go:500 +0x1af main.main.func2(0xc04203a180) C:/Users/tanteng/Go/src/examples/channel_close.go:18 +0x6b created by main.main C:/Users/tanteng/Go/src/examples/channel_close.go:21 +0xb8 exit 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() }
看完上述內容,你們掌握使用Golang怎么關閉channel的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注創新互聯行業資訊頻道,感謝各位的閱讀!
分享名稱:使用Golang怎么關閉channel
本文URL:http://m.newbst.com/article0/jesgio.html
成都網站建設公司_創新互聯,為您提供商城網站、動態網站、品牌網站制作、標簽優化、定制網站、建站公司
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯