expvar 默认注册在 /debug/vars 但需显式启用,常见因未导入 _ "net/http/pprof" 或未手动注册 handler 导致 404;仅支持基本类型序列化,存复杂类型会 panic;中文乱码多因请求头缺失或字段名错误;生产环境有极小性能风险且易暴露敏感信息。

expvar 为什么默认打开却看不到数据
Go 标准库的 expvar 包默认注册在 /debug/vars,但前提是你的 HTTP 服务显式启用了它——不是所有服务都自动挂载。常见错误是:启动了 http.ListenAndServe,但没调用 http.HandleFunc 或没导入 _ "net/http/pprof"(后者会顺带注册 /debug/vars)。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 确保已导入
_ "net/http/pprof"(哪怕不用 pprof,它也会注册expvar的 handler) - 或手动注册:
http.HandleFunc("/debug/vars", expvar.Handler().ServeHTTP) - 检查是否监听了正确端口,且路由未被中间件拦截(比如 Gin 默认不透传
/debug/*) - curl
http://localhost:8080/debug/vars应返回 JSON;如果 404,说明 handler 没挂上
自定义指标时 panic: interface{} is not registered for json encoding
往 expvar.NewMap 或 expvar.Publish 里塞结构体、指针、函数等非基本类型,expvar 内部用 json.Marshal 序列化时会直接 panic。这不是 bug,是设计限制:只支持 int、float64、string、map[string]interface{}、[]interface{} 和它们的组合。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 避免存
*sync.Mutex、time.Time、自定义 struct(除非你提前转成 map 或 string) - 时间戳统一用
time.Now().Unix()存为int64 - 计数器优先用
expvar.Int,Gauge 用expvar.Float,字符串状态用expvar.String - 复杂状态可先
json.Marshal成[]byte,再转string存入expvar.String
用 curl 查看指标时中文乱码或字段缺失
expvar 返回的是纯 JSON,Content-Type 默认是 text/plain; charset=utf-8,但某些旧版 curl 或代理可能忽略 charset,导致终端显示异常;更常见的是字段“缺失”——其实是 Go 运行时只暴露了部分内置变量(如 memstats、cmdline),而你注册的自定义指标名拼错了,或没调用 expvar.Publish。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 加
-H "Accept: application/json"显式声明请求头 - 用
jq解析:curl -s http://localhost:8080/debug/vars | jq '.my_counter',避免肉眼漏看 - 检查自定义变量名是否含非法字符(只允许字母、数字、下划线)
- 确认
expvar.Publish("my_counter", myCounter)在main()开始后执行,不能晚于 HTTP server 启动
生产环境开 expvar 有没有性能风险
有,但极小。每次请求 /debug/vars 都会触发一次全量 json.Marshal,包括 runtime.ReadMemStats —— 这个调用本身是 O(1),但若你注册了大量(>1000 个)自定义指标,或某个 expvar.Func 内部做了耗时操作(比如查 DB),就会拖慢响应。更隐蔽的风险是:暴露敏感信息(如配置项、连接串)到公开接口。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 仅在内网或带鉴权的路径暴露(例如反向代理层加 IP 白名单或 Basic Auth)
- 避免在
expvar.Func中做任何阻塞操作;如需聚合,改用后台 goroutine 定期更新expvar.Int - 上线前用
ab -n 1000 -c 100 http://x/debug/vars测压,观察 P95 延迟是否突增 - 不要把
os.Getenv或flag.Lookup结果直接塞进 expvar,尤其含密码字段
真正容易被忽略的是:expvar 不提供采样、聚合、过期机制,它只是个快照。想长期观测,得配 Prometheus 抓取,或自己加定时 dump 到日志——别指望靠 curl 手动刷屏看趋势。

















