无法使用msg:= rang msgs阻止rabbitmq消息(msgs是一个频道)

时间:2016-09-22 10:32:39

标签: go rabbitmq

我复制了rabbitmq go示例并改变了一点进行测试。

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()从服务器等待msg。它现在会退出。原始代码和更改代码之间有什么区别吗? 非常感谢!

1 个答案:

答案 0 :(得分:0)

这是垃圾收集和密切推迟的简单错误。

假设您的代码库与此类似,因为您省略了示例中的代码。

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的连接并同时关闭它。因此,当您在频道上调整范围时,它已经关闭。

  

defer conn.Close()

     

defer ch.Close()

一旦方法connection退出,这些告诉将调用channelListenRabbit上的关闭方法。此外,通过初始化该方法中的连接和通道,您将使所有这些对象都被垃圾收集,因为一旦moethod完成,就不会有任何引用。

你需要在你的主要内容中初始化所有内容,以便它保持打开和工作状态,或者你可以返回连接和通道上的方法返回值,但记得在完成后处理/关闭它们。

rabbit git repository上的代码示例是正确的方法,但它只是设计代码的一种方式。您需要了解面向对象编程的一些基本概念,go中的编码(引用,延迟,垃圾收集等)以及您要做的事情,以便您可以决定使用哪种最佳设计。

现在只需使用示例代码即可。