goroutine 泄漏指 goroutine 启动后永远无法退出,持续占用栈内存和调度资源。典型场景:向无接收者的 channel 发送(或对 nil channel 收发)永久阻塞;for-select 循环缺少退出分支;HTTP 客户端未设超时导致读阻塞;锁使用不当永久等锁;长循环里 time.After 堆积 timer。
排查手段:生产环境接入 net/http/pprof,观察 /debug/pprof/goroutine 的数量曲线和完整堆栈,泄漏的 goroutine 会呈现大量相同调用栈;监控 runtime.NumGoroutine 的趋势;测试中可用 uber 的 goleak 库在用例结束时校验 goroutine 是否归零。
防范模式:每个 goroutine 都要有明确退出路径,用 context 或 quit channel 传递取消信号;发送遵循'要么缓冲足够,要么确认有接收者';IO 一律设 deadline。
func run(ctx context.Context, ch chan<- int) {
for {
select {
case <-ctx.Done():
return // 保证可退出
case ch <- work():
}
}
}
追问方向:泄漏与内存泄漏的叠加效应、如何给存量代码补退出路径。