2016-09-22 12 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

相關問題