来源:自学PHP网 时间:2019-08-07 16:47 作者:小飞侠 阅读:次
[导读] golang中for循环遍历channel时需要注意的问题详解...
前言 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被关闭的问题。 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对自学php网的支持。 |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com