go - 无法使用 msg := rang msgs (msgs is a channel) 阻止 rabbitmq msg

标签 go rabbitmq

我复制了 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 退出,这些告诉去调用 connectionchannel 上的 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/

相关文章:

go - channel 多路复用器

java - 与rabbitmq java客户端API交换的列表绑定(bind)

c# - RabbitMQ C# 验证消息已发送

sockets - 通讯应用程序。数据存储与消息队列

go - 如何处理区分大小写的导入冲突

json - 质疑如何在Golang中将mongodb的命令转换为Bson

go - 通过 SetDeadline() 为 TCP 监听器设置超时

go - 禁用HTML代码Goland IDE中的SQL语法突出显示

c# - RabbitMQ 事务在队列关闭时无一异常(exception)地提交

java - rabbitmq 具有基于属性的自定义排序