我复制了 rabbitmq go example 并稍作改动以进行测试。
Example URL .正常工作
代码结构:
func main() {
//dial rabbit server
//declare channel/exange/queue
msgs, err := ch.Consume() //typeof(msgs)=<-chan Delivery
forever := make(chan bool)
go func() {
for d := range msgs {
log.Printf("Received a message: %s", d.Body)
}
}()
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
<-forever
}
但是如果我将一些代码放入函数中,例如:
func ListenRabbit() (<-chan Delivery, error) {
//dial rabbit server
//declare channel/exange/queue
msgs, err := ch.Consume() //typeof(msgs)=<-chan Delivery
return msgs, err
}
func main(){
msgs, _ := ListenRabbit()
for d := range msgs {
log.Printf("Received a message: %s", d.Body)
}
}
无法阻止 main() 等待来自服务器的消息。它会立即退出。原始代码和更改后的代码之间有什么区别吗? 非常感谢!
最佳答案
这是垃圾收集和关闭延迟的简单错误。
假设您的代码库与此类似,因为您省略了示例中的代码。
package main
import (
"log"
"github.com/streadway/amqp"
)
func failOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s: %s", msg, err)
}
}
func ListenRabbit() (<-chan amqp.Delivery, error) {
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close()
ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
defer ch.Close()
q, err := ch.QueueDeclare(
"hello", // name
false, // durable
false, // delete when usused
false, // exclusive
false, // no-wait
nil, // arguments
)
failOnError(err, "Failed to declare a queue")
msgs, err := ch.Consume(
q.Name, // queue
"", // consumer
true, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
failOnError(err, "Failed to register a consumer")
return msgs, err
}
func main() {
msgs, _ := ListenRabbit()
for d := range msgs {
log.Printf("Received a message: %s", d.Body)
}
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
}
您的问题是您在 ListenRabbit 方法上初始化与 Rabbit 的连接并同时关闭它。因此,当您在 channel 上进行测距时,它已经关闭。
defer conn.Close()
defer ch.Close()
一旦方法 ListenRabbit
退出,这些告诉去调用 connection
和 channel
上的 Close 方法。此外,通过在该方法中初始化连接和 channel ,您将让所有这些对象被垃圾收集,因为一旦 moethod 完成,就不会留下对它们的引用。
您需要在您的 main 中初始化所有这些,以便它保持打开和工作,或者您可以在您的方法返回值上返回连接和 channel ,但请记住在完成后处理/关闭它们。
rabbit git repository 上的代码示例是正确的方法,但这只是设计代码的一种方法。您需要了解面向对象编程、go 编码(引用、延迟、垃圾回收等)的一些基本概念以及您想要做什么,以便您可以决定使用什么是最佳设计。
目前仅使用示例代码就足够了。
关于go - 无法使用 msg := rang msgs (msgs is a channel) 阻止 rabbitmq msg,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39636684/