您好,登錄后才能下訂單哦!
前言
for循環是Go語言唯一的循環結構,最近在做一個基于RabbitMQ的應用,由于官方的qos沒有golang的版本,所以出了一點問題。
問題代碼如下:
_, 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) }
發現消費到10條消息,進程就退出了,但是exit code為0,表示系統是正常退出,由于做了日志記錄可以確定消費了10條,所以初步確定是qos相關問題。
排查過程
測試代碼
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) } }
執行輸出
0xc420086008 0xc420086008 0xc420086008 0xc420086008 0xc420086008 0xc420086008 0xc420086008 0xc420086008 0xc420086008 0xc420086008
到這里才煥然大悟,for循環中,如果循環變量不是指針,那么每次的變量是同一個,不過值變了。,所以上例中的RabbitMQ go協程消費消息那里,需要直接傳遞值而不是指針,經過測試之后發現,問題確實解決了。
題外話
測試代碼那里,如果不close掉channel是會發生死鎖的,原因是 當for循環讀完channel的10個值之后會繼續嘗試讀取下一個,而由于channel為空又沒關閉,會一直阻塞形成死鎖
TOOD
研究RabbitMQ Consumer部分的源碼來看看消費channel被關閉的問題。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。