溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

golang中for循環(huán)遍歷channel時(shí)需要注意的問(wèn)題詳解

發(fā)布時(shí)間:2020-09-12 20:16:16 來(lái)源:腳本之家 閱讀:1604 作者:xialeistudio 欄目:編程語(yǔ)言

前言

for循環(huán)是Go語(yǔ)言唯一的循環(huán)結(jié)構(gòu),最近在做一個(gè)基于RabbitMQ的應(yīng)用,由于官方的qos沒(méi)有g(shù)olang的版本,所以出了一點(diǎn)問(wèn)題。

問(wèn)題代碼如下:

_, ch, err := component.NewRabbitMQ()
if err != nil {
 panic(err)
}
if err := ch.Qos(10, 0, true); err != nil {
 panic(err)
}
msgs, err := ch.Consume("push", "", false, false, false, false, nil)
if err != nil {
 panic(err)
}
for m := range msgs {
 go func(d *amqp.Delivery) {
   defer func() { d.Ack(false) }
   // 處理消息
  }(&m)
 }

發(fā)現(xiàn)消費(fèi)到10條消息,進(jìn)程就退出了,但是exit code為0,表示系統(tǒng)是正常退出,由于做了日志記錄可以確定消費(fèi)了10條,所以初步確定是qos相關(guān)問(wèn)題。

排查過(guò)程

  • 首先是把d的tag打印出來(lái),發(fā)現(xiàn)全部是一樣的,可以確定是重復(fù)的一條消息
  • 一開(kāi)始想到可能是經(jīng)典的go協(xié)程執(zhí)行在for循環(huán)結(jié)束以后導(dǎo)致的,但是看我的代碼不屬于這種情況,有使用&m保證每一條消息都是不同循環(huán)傳入的。所以判斷可能是for循環(huán)的傳遞問(wèn)題。
  • 確定方向之后開(kāi)始寫(xiě)了一個(gè)測(cè)試項(xiàng)目用來(lái)驗(yàn)證我的想法是否正確。

測(cè)試代碼

package main
import "fmt"
func main() {
 ch := make(chan int, 10)
 for i := 0; i < 10; i++ {
 ch <- i
 }
 close(ch)
 for v := range ch {
 fmt.Println(&v)
 }
}

執(zhí)行輸出

0xc420086008
0xc420086008
0xc420086008
0xc420086008
0xc420086008
0xc420086008
0xc420086008
0xc420086008
0xc420086008
0xc420086008

到這里才煥然大悟,for循環(huán)中,如果循環(huán)變量不是指針,那么每次的變量是同一個(gè),不過(guò)值變了。,所以上例中的RabbitMQ go協(xié)程消費(fèi)消息那里,需要直接傳遞值而不是指針,經(jīng)過(guò)測(cè)試之后發(fā)現(xiàn),問(wèn)題確實(shí)解決了。

題外話

測(cè)試代碼那里,如果不close掉channel是會(huì)發(fā)生死鎖的,原因是 當(dāng)for循環(huán)讀完channel的10個(gè)值之后會(huì)繼續(xù)嘗試讀取下一個(gè),而由于channel為空又沒(méi)關(guān)閉,會(huì)一直阻塞形成死鎖

TOOD

研究RabbitMQ Consumer部分的源碼來(lái)看看消費(fèi)channel被關(guān)閉的問(wèn)題。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)億速云的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎ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)容。

AI