2016-09-22 11 views
0

我复制rabbitmq go例子,并稍加改动以测试。未能阻止rabbitmq msg使用msg:= rang msgs(msgs是一个通道)

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()不能阻止从服务器等待味精。它现在将退出。原始代码和改变代码之间是否有区别? 非常感谢!

回答

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:[email protected]: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") 
} 

你的问题是,你正在初始化连接到Rabbit的ListenRabbit方法并关闭它在同一时间。所以,当你在频道上播放时,它已经关闭了。

defer conn.Close()

defer ch.Close()

这些告诉去呼吁connectionchannel一旦方法ListenRabbit退出关闭方法。同样,通过初始化该方法中的连接和通道,您将使所有这些对象都被垃圾收集,因为一旦moethod完成后没有引用将留给他们。

你需要在你的主体中初始化所有这些,以便它保持开放和正常工作,或者你可以在方法返回值上返回连接和通道,但记得在完成后处置/关闭它们。

rabbit git repository上的代码示例是正确的方式,但它只是设计代码的一种方式。你需要了解一些面向对象编程的基本概念,在go中编码(引用,延迟,垃圾回收等)以及你想要做什么,这样你才能决定使用什么样的最佳设计。

现在只需使用示例代码就足够了。

+0

谢谢。我忘了“推迟”操作...并感谢您对设计的评论:) –

+0

不用担心,只是不要初始化连接和通道然后处置它,将它返回到方法 – dmportella

相关问题