This is simple mistake with garbage collection and close defers.
Assuming your codebase is something similar to this since you ommitted the code from your example.
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")
}
Your problem is that you are initialising the connection to Rabbit on the ListenRabbit method and closing it at the same time. So when you range on the channel it is already closed.
defer conn.Close()
defer ch.Close()
These tell go to call the Close methods on the connection
and channel
once the method ListenRabbit
exits. Also by initialising the connection and channel in that method you are leaving all those objects to be garbage collected since no references will be left to them once the moethod finishes.
You need to initialise all of that in your main so it keeps it open and working or you can return the connection and channel on you method return values but remember to dispose/close them once you are done.
The code example on the rabbit git repository is the right way to do it but it is just one way of designing the code. You need to understand some of the basic concepts of object oriented programming, coding in go (references, defers, garbage collection etc) and what you looking to do so you can decide what is the best design to use.
For now just using the example code is good enough.