真正内存泄漏在go中极少是对象未被gc,多因goroutine卡住不退或资源未显式释放;pprof显示heapinuse单向上涨、numgoroutine只增不减可锁定问题。

真正内存泄漏在 Go 里极少是“对象没被 GC”,绝大多数是 goroutine 卡住不退 或 资源未显式释放 导致的持续内存增长。pprof 显示 HeapInuse 单向上涨、runtime.NumGoroutine() 只增不减,基本就能锁定这两类问题。
goroutine 泄漏:别信“它自己会结束”
goroutine 启动后卡在 、<code>time.Sleep、http.Get 或 select 无响应分支,就不会返回,栈内存(至少 2KB)、闭包变量、引用的对象全锁死——GC 完全无效。
- 检查方法:访问
http://localhost:6060/debug/pprof/goroutine?debug=2,搜索chan receive、semacquire、IO wait - 所有阻塞操作必须进
select,且第一个case必须是 - 错误写法:
go func() { for { doWork(); time.Sleep(1 * time.Second) } }()—— ctx cancel 后照样睡 - 正确写法:
ticker := time.NewTicker(1 * time.Second); defer ticker.Stop(); for { select { case - channel 由 sender 创建,就该由 sender 关闭;receiver 必须用
ok判断退出,不能只靠for range ch
资源未关闭:defer 不是万能保险
defer 只在函数 return 时触发。如果 goroutine 卡死或陷入死循环,defer f.Close() 永远不执行,文件描述符、DB 连接、HTTP body 就一直开着。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- HTTP 请求必须用
req.WithContext(ctx)+client.Do(),响应体拿到后立刻resp.Body.Close() - 数据库查询优先用
QueryContext、ExecContext,别用裸Query - 打开文件后,哪怕后续逻辑 panic,也要确保
defer f.Close()在os.Open后紧跟着写 - timer/ticker 必须
defer ticker.Stop(),哪怕已加 ctx 控制——两者不互斥,缺一不可
map/sync.Map 残留:不是缓存,是内存黑洞
用时间戳、请求 ID、用户 session 作 key 塞进全局 map,又不主动 delete,map 本身和 value 引用的所有对象就永远驻留。sync.Map 同样不会自动驱逐。
- 明确生命周期:局部 map 用完即清,
for k := range m { delete(m, k) } - 需要缓存时,选带 TTL 的库(如
github.com/bluele/gcache),或自己封装定时清理 goroutine - 避免把大 struct 直接塞进 map value——改用指针或 ID,降低 map 自身膨胀速度
- 别依赖
runtime.MemStats.HeapInuse看泄漏,重点看alloc_space差分:抓两个 heap 快照,用go tool pprof -diff_base找高频分配未释放的函数
pprof 分析要抓对指标
只看 inuse_space 会漏掉 90% 的真实泄漏。很多泄漏单次分配小、残留少,但在 alloc_space 上持续上涨。
- 空载运行 2 分钟后抓第一个 heap 快照:
wget "http://localhost:6060/debug/pprof/heap?gc=1" -O heap1.pprof - 再等 5 分钟抓第二个:
wget ... -O heap2.pprof - 运行
go tool pprof -diff_base heap1.pprof heap2.pprof,top查alloc_space增量最大的函数 - 点进去
list <funcname></funcname>,直接定位到哪行代码在高频 new 且没释放 - goroutine 快照也要做差分:
go tool pprof -base init.pb.gz later.pb.gz,查新增 goroutine 的栈帧
真正难排查的不是“哪里多占了内存”,而是“谁在 hold 住不该 hold 的引用”。pprof 的 alloc_space 差分和 goroutine 快照对比,比盯着 inuse_space 高峰有用十倍。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










