CloudAMQP with Go
We recommend amqp-client.go. It reconnects automatically, recovers queues and consumers after a reconnect, and has no dependencies.
go mod init example.com/cloudamqp-example
go get github.com/cloudamqp/amqp-client.go
Publish and consume
Save the publisher as publisher.go:
package main
import (
"context"
"log"
amqp "github.com/cloudamqp/amqp-client.go"
)
// runPublisher publishes a persistent message and returns once the broker has confirmed it.
func runPublisher(ctx context.Context, c *amqp.Client, queue, message string) error {
q, err := c.Queue(ctx, queue, nil)
if err != nil {
return err
}
if err := q.Publish(ctx, amqp.Message{Body: message}); err != nil {
return err
}
log.Printf(" [x] Sent '%s'", message)
return nil
}
Save the consumer as worker.go in the same directory:
package main
import (
"context"
"log"
amqp "github.com/cloudamqp/amqp-client.go"
)
// runWorker calls handler for each message until ctx is done, with a prefetch of 10.
// The message is acked when handler returns nil, and requeued when it returns an error.
func runWorker(ctx context.Context, c *amqp.Client, queue string, handler func(message string) error) error {
q, err := c.Queue(ctx, queue, nil)
if err != nil {
return err
}
_, err = q.Subscribe(ctx, func(ctx context.Context, d *amqp.Delivery) error {
return handler(string(d.Body))
}, &amqp.SubscribeOptions{Prefetch: 10})
if err != nil {
return err
}
log.Println(" [*] Waiting for messages. To exit press CTRL+C")
<-ctx.Done()
return nil
}
Save the entry point as main.go. It connects using CLOUDAMQP_URL, which
you set to the AMQP URL from your instance’s details page in the CloudAMQP
console. Without it, the example connects to a local broker.
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
amqp "github.com/cloudamqp/amqp-client.go"
)
func main() {
if len(os.Args) != 2 || (os.Args[1] != "publish" && os.Args[1] != "worker") {
fmt.Fprintln(os.Stderr, "Usage: go run . publish|worker")
os.Exit(2)
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
c, err := connect(ctx)
if err != nil {
log.Fatal(err)
}
defer c.Close()
if os.Args[1] == "publish" {
err = runPublisher(ctx, c, "hello", "Hello CloudAMQP!")
} else {
err = runWorker(ctx, c, "hello", func(message string) error {
log.Printf(" [x] Received '%s'", message)
return nil
})
}
if err != nil {
log.Fatal(err)
}
}
// connect connects to CLOUDAMQP_URL, and reconnects if the connection is lost.
func connect(ctx context.Context) (*amqp.Client, error) {
url := os.Getenv("CLOUDAMQP_URL")
if url == "" {
url = "amqp://guest:guest@localhost"
}
return amqp.NewClient(ctx, url, nil)
}
Run go run . worker in one terminal and go run . publish in another.
A runnable example is in go/amqp-client in cloudamqp/examples.
Good to know
- Connect with the URL.
amqp.NewClient(ctx, url, nil), where the URL is the one on your instance’s details page in the CloudAMQP console. Withamqps://the server certificate is verified. - Messages are safe by default.
Publishsends persistent messages and returns once the broker has confirmed them. - Messages are acked when your handler returns nil. If it returns an error or panics, the message is requeued. Make handlers idempotent, because a message can be delivered again after a reconnect.
- Set a prefetch limit with
SubscribeOptions.Prefetch, so a consumer doesn’t buffer more messages than it can handle.
See the API reference for codecs, RPC and the low-level API.
Other Go libraries
- amqp091-go, maintained by the RabbitMQ team, without automatic reconnection