连不上 rabbitmq 八成是 url 写错或 vhost 未编码;amqp.dial 必须用标准 amqp uri,如"amqp://guest:guest@localhost:5672/%2f",/需编码为%2f,云环境须开放5672端口。

连不上 RabbitMQ?八成是 URL 写错或 vhost 没编码,不是代码问题。
amqp.Dial 的 URI 格式必须严格符合标准
Go 里用 amqp.Dial 连接 RabbitMQ,传的不是 HTTP 地址,而是 AMQP URI。常见错误包括:
- 写成
"amqp://guest:guest@localhost:5672/"—— 缺少 vhost 编码,/必须是%2F - 写成
"amqp://guest:guest@localhost:5672"—— 端口后漏了/,会解析失败 - 云环境(如阿里云、腾讯云)没开安全组 5672 端口,报
dial tcp: i/o timeout,不是密码错
正确写法:"amqp://guest:guest@localhost:5672/%2F"。vhost 是必填项,哪怕用默认 /,也得编码。
ch.Publish 发不出消息?检查 exchange、routing key 和绑定关系
调用 ch.Publish 返回 nil 错误 ≠ 消息已送达。RabbitMQ 默认“发完即忘”,不校验目标是否存在。容易卡住的地方:
- exchange 名为空字符串
""(走默认 direct exchange),但 routing key 不等于队列名 → 消息直接丢弃 - 自定义 exchange 声明时没设
durable: true,重启后 exchange 消失,后续绑定失效 - 队列没显式
QueueDeclare,只靠Consume自动创建 —— auto-delete 队列在消费者断开后立即销毁,不可靠 - 想让消息投递失败时有反馈,加
mandatory: true并提前用ch.NotifyReturn注册回调
消息丢了?持久化不是单开关,得三处配齐
标了 DeliveryMode: amqp.Persistent ≠ 消息一定不丢。RabbitMQ 的持久化是端到端链条:
- 生产者发消息时设
DeliveryMode - exchange 声明时设
durable: true(默认直连 exchange 已 durable,但自定义的必须显式传) - 队列声明时设
durable: true,否则重启后队列消失,持久消息无处可存
缺一环,重启或崩溃后消息就没了。消费者端还要配合手动 Ack,否则消息可能被重复投递或卡在 unacked 状态。
消费者收不到消息?先查 autoAck、Qos 和 channel 复用
最典型的现象:程序没报错、ch.Consume 返回了 msgs 通道,但协程一直阻塞——其实消息早到了,只是被卡住了:
-
autoAck: true开着,消息一发就确认,崩了就丢;建议关掉,自己控制Ack/Nack - 没调
ch.Qos,默认 prefetch=0(不限制),大量消息涌入导致 Go channel 缓冲区满、协程阻塞 - 多个 goroutine 共用一个
amqp.Channel—— AMQP channel 不是并发安全的,会静默出错或消息错乱
每个 goroutine 应该用独立 channel,或加锁保护;Qos 推荐设为 1~10,视处理耗时调整。
真正难调试的点往往不在逻辑,而在连接参数、vhost 编码、exchange/queue 的 durable 属性、以及 channel 生命周期管理 —— 这些地方一错,现象模糊,日志又不报错,只能靠对照 AMQP URI 规范和声明参数逐项核对。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











