默认应看allocs或触发gc后再采heap以防误判内存泄漏;/debug/pprof/heap返回404是因未正确导入import _ "net/http/pprof"或未在defaultservemux注册,自定义mux需手动挂载路由;分析时flat反映函数自身分配,cum反映整条调用链累计分配。

默认看 inuse_space 容易误判“没泄漏”,真要查内存问题,得切到 allocs 或手动触发 GC 后再采 heap。
为什么 /debug/pprof/heap 返回 404?
不是端口没开,也不是路由写错,是 net/http/pprof 的注册没生效。
- 必须加这行:
import _ "net/http/pprof"(下划线不能少,否则编译器会优化掉) - HTTP server 要在主逻辑前启动,推荐用 goroutine:
go http.ListenAndServe("localhost:6060", nil) - 已有 mux(如 gin、echo)?别起新服务,改用:
r.HandleFunc("/debug/pprof/", http.HandlerFunc(pprof.Index)) - 生产环境务必绑定
127.0.0.1:6060,绝不要用0.0.0.0:6060
top 里 flat 和 cum 到底该信哪个?
flat 是函数自身直接分配的内存,cum 是它及所有下游调用链累计分配的总量。
- 定位“谁申请最多”看
flat:比如strings.Builder.Writeflat很高 → 它自己在疯狂拼接字符串 - 定位“谁触发了高分配链”看
cum:比如http.(*ServeMux).ServeHTTPcum高但flat低 → 它只是入口,真干活的是下游 handler - 常用组合:先
top -cum找调用链顶端,再list 函数名看具体哪行make或append在扩容
怎么抓一次真正有效的 heap profile?
线上不能停服务,不能拖慢响应,更不能把 profile 文件留在磁盘上——得流式拉取 + 即时分析。
- 先强制 GC:
curl "http://localhost:6060/debug/pprof/heap?gc=1",再等 30 秒后重采,对比HeapInuse是否持续上涨 - 怀疑高频临时对象堆积?用
allocs:go tool pprof http://localhost:6060/debug/pprof/allocs,然后top -focus alloc或启动时加-sample_index=alloc_objects - 抓完别急着退出进程,至少保留 30 秒,避免 profile 被 GC 清掉
- 流式分析示例:
curl -s "http://$IP:6060/debug/pprof/heap" | go tool pprof -
容易被忽略的是:sync.Pool 缓存的对象不会出现在 heap profile 里,但如果它的 New 函数创建了大底层数组(比如过大的 bytes.Buffer),仍会推高 alloc_space。这种泄漏不会体现在 inuse_space 上,但会真实吃掉内存。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











