golang中for循环遍历channel时需要注意的问题详解

作者:xialeistudio 时间:2024-04-29 13:05:16 

前言

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相关问题。

排查过程

  • 首先是把d的tag打印出来,发现全部是一样的,可以确定是重复的一条消息

  • 一开始想到可能是经典的go协程执行在for循环结束以后导致的,但是看我的代码不属于这种情况,有使用&m保证每一条消息都是不同循环传入的。所以判断可能是for循环的传递问题。

  • 确定方向之后开始写了一个测试项目用来验证我的想法是否正确。

测试代码


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被关闭的问题。

来源:https://www.ddhigh.com/2018/04/05/golang-for-over-channels.html

标签:golang,for循环,channel
0
投稿

猜你喜欢

  • Python中如何引入第三方模块

    2023-08-27 08:34:48
  • Java连接MYSQL数据库的实现步骤

    2024-01-24 01:23:33
  • google 的设计原则和LOGO手绘

    2008-05-20 12:16:00
  • 为MySQL创建高性能索引

    2024-01-19 09:22:32
  • dl,dt,dd标签 VS 传统table实现数据列表

    2009-08-02 20:45:00
  • 在Python中测试访问同一数据的竞争条件的方法

    2023-03-29 15:04:06
  • 写给新手同学的vuex快速上手指北小结

    2024-04-27 16:03:33
  • Oracle中PL/SQL的块与表达式

    2024-01-28 21:30:34
  • python 多态 协议 鸭子类型详解

    2023-10-03 11:53:00
  • Python如何识别 MySQL 中的冗余索引

    2024-01-13 13:44:46
  • javascript 实现的完全兼容鼠标滚轴缩放图片的代码

    2024-04-10 16:09:43
  • python的endswith()的使用方法及实例

    2023-04-30 04:42:11
  • 简单的Apache+FastCGI+Django配置指南

    2021-01-27 10:09:16
  • python在windows下实现备份程序实例

    2021-08-15 19:34:53
  • 解析WordPress中函数钩子hook的作用及基本用法

    2023-07-08 03:27:52
  • Python实战之OpenCV实现猫脸检测

    2021-02-07 16:56:24
  • 运行(runCode)复制(copyCode)保存(saveCode)代码框方法

    2007-10-21 08:41:00
  • numpy:找到指定元素的索引示例

    2022-05-18 22:29:37
  • 在django中图片上传的格式校验及大小方法

    2023-04-02 23:12:56
  • Vue自定义指令中无法获取this的问题及解决

    2024-05-29 22:46:46
  • asp之家 网络编程 m.aspxhome.com