Go环境需开启GO111MODULE=on、配置GOPROXY国内源;Consul服务端用-dev模式时必须加-client=0.0.0.0 -advertise=127.0.0.1;注册服务须带TTL健康检查并立即UpdateTTL("pass")。

go 环境必须先装稳,否则 consul 客户端连编译都过不了——别跳步骤。
确认 Go 已正确安装并启用模块
不是只要 go version 能输出就完事。关键看三件事:
-
GO111MODULE=on:必须开启,否则go get会忽略go.mod,依赖乱套 -
GOPROXY指向国内源(如https://goproxy.cn):不配这个,go get github.com/hashicorp/consul/api十有八九超时失败 -
go env -w GOPATH不强制设,但go mod init your-module-name必须在项目根目录执行,生成go.mod
验证命令:
go env GO111MODULE GOPROXY
输出应为 on 和有效代理地址。若不是,立刻补:
立即学习“go语言免费学习笔记(深入)”;
go env -w GO111MODULE=on<br>go env -w GOPROXY=https://goproxy.cn,direct
Consul 服务端不能只跑 consul agent -dev
开发阶段用 -dev 模式省事,但它默认不监听外部请求,且 Address 和 advertise_addr 都是空的——导致你注册的服务在发现端查不到 Service.Address,只返回 Node.Address(即 Consul 节点 IP,不是你的服务 IP)。
本地调试请用:
consul agent -dev -client=0.0.0.0 -bind=127.0.0.1 -advertise=127.0.0.1
这样客户端注册时填 "" 或 "127.0.0.1" 都能被正确路由,服务发现拿到的 srv.Service.Address 才是可用值。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
常见错误现象:client.Health().Service("my-service", "", false, &q) 返回实例,但 srv.Service.Address == ""、srv.Service.Port == 0——基本就是 -advertise 没设。
注册服务必须带健康检查,且注册后立刻 Pass
Consul 默认把没健康检查的服务当“不健康”,根本不会返回给发现方。光写 RegisterInstance 或 Register 是无效的。
实操要点:
- 用
&api.AgentServiceCheck{TTL: "30s"}最简方式启用 TTL 健康检查(别用 HTTP 检查起步,容易卡在 /health 返回 200 却不校验 DB 连接) - 注册成功后,**立刻**调一次
client.Agent().UpdateTTL("service:your-id", "", "pass"),否则 Consul 会等第一个 30s 过期才认为服务“活了” - 确保
main()不退出:http.ListenAndServe(":8080", nil)必须阻塞住进程;如果它后面跟着os.Exit(0)或没这行,服务几秒内就被 Consul 自动注销
示例关键片段:
registration := &api.AgentServiceRegistration{<br> ID: "user-service-1",<br> Name: "user-service",<br> Address: "127.0.0.1",<br> Port: 8080,<br> Check: &api.AgentServiceCheck{<br> TTL: "30s",<br> },<br>}<br>client.Agent().ServiceRegister(registration)<br>client.Agent().UpdateTTL("service:user-service-1", "", "pass") // ? 这行不能少服务发现时别硬编码 localhost 地址
发现端代码里写死 "http://localhost:8500" 看似方便,但一旦服务部署到 Docker 或 K8s,Consul 客户端地址就不是 localhost 了。
更稳妥的做法:
- 从环境变量读取:
consulAddr := os.Getenv("CONSUL_ADDR"),默认 fallback 到"http://127.0.0.1:8500" - 构造 client 时显式传入配置:
config.Address = consulAddr,而不是依赖api.DefaultConfig() - 服务发现结果里的
srv.Service.Address和srv.Service.Port直接拼成 URL,不要拼"http://localhost:" + port
容易踩的坑:本地跑通了,一丢进 Docker 就报 connection refused——八成是发现端还在连 localhost:8500,而容器里根本没有这个地址。
服务注册和发现真正卡住人的地方,从来不是语法,而是 Consul 的健康状态流转逻辑和网络地址可见性。多花两分钟确认 -advertise 和 UpdateTTL,比反复查日志快得多。

















