您好,登錄后才能下訂單哦!
使用Golang怎么關(guān)閉channel?相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。
關(guān)于Go channel設(shè)計(jì)和規(guī)范的批評(píng):
在不能更改channel狀態(tài)的情況下,沒(méi)有簡(jiǎn)單普遍的方式來(lái)檢查channel是否已經(jīng)關(guān)閉了
關(guān)閉已經(jīng)關(guān)閉的channel會(huì)導(dǎo)致panic,所以在closer(關(guān)閉者)不知道channel是否已經(jīng)關(guān)閉的情況下去關(guān)閉channel是很危險(xiǎn)的
發(fā)送值到已經(jīng)關(guān)閉的channel會(huì)導(dǎo)致panic,所以如果sender(發(fā)送者)在不知道channel是否已經(jīng)關(guān)閉的情況下去向channel發(fā)送值是很危險(xiǎn)的
所以Golang 內(nèi)建的 close 方法可以關(guān)閉 channel,如果往已經(jīng)關(guān)閉的 channel 發(fā)送數(shù)據(jù),則會(huì)報(bào)錯(cuò):panic: close of closed channel.
看如下代碼,在一段時(shí)間內(nèi),生產(chǎn)者可以不斷往 channel 寫(xiě)入數(shù)據(jù),消費(fèi)者進(jìn)行處理,一段時(shí)間后 channel 關(guān)閉了,這個(gè)時(shí)候如果還有數(shù)據(jù)往 channel 發(fā)送,程序就會(huì)報(bào)錯(cuò)。
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() }
多運(yùn)行幾次出錯(cuò)的概率會(huì)比較大:
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
如何優(yōu)雅關(guān)閉 channel
那么在往通道發(fā)數(shù)據(jù)前如何判斷通道是否關(guān)閉呢?
1._,ok := <- jobs
此時(shí)如果 channel 關(guān)閉,ok 值為 false,如果 channel 沒(méi)有關(guān)閉,則會(huì)漏掉一個(gè) jobs
2.使用 select 方式
再創(chuàng)建一個(gè) channel,叫做 timeout,如果超時(shí)往這個(gè) channel 發(fā)送 true,在生產(chǎn)者發(fā)送數(shù)據(jù)給 jobs 的 channel,用 select 監(jiān)聽(tīng) timeout,如果超時(shí)則關(guān)閉 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() }
看完上述內(nèi)容,你們掌握使用Golang怎么關(guān)閉channel的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。