协程泄漏指在原本应该结束的时候,协程持续存在,这时候可能会导致协程和相关的资源(如内存、锁等)无法释放,导致程序出现内存泄漏和死锁等问题。
以下是一些避免协程泄露的方法:
  1. 确保在协程退出时,所有资源都被正常释放。例如,使用 defer 延迟调用函数来确保资源在函数返回前被释放: func foo() { mu := &sync.Mutex{} mu.Lock() defer mu.Unlock() // do something }
  1. 使用 select 语句中的超时或退出信号来控制协程生命周期,确保在需要的时候退出: func worker(ctx context.Context, stopCh <-chan struct{}) { for { select { case <-stopCh: return default: // do something } } }
  1. 使用 sync.WaitGroup 来确保在所有协程结束前,所有资源都被正确释放。例如,在启动协程之前添加计数器,并在每个协程开始和结束时调用 Add() 和 Done(): func main() { wg := &sync.WaitGroup{} stopCh := make(chan struct{}) for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() worker(stopCh) }() } // do something close(stopCh) wg.Wait() }
  1. 在使用协程的时候,一定要确保使用可重入的函数,避免在协程中使用不能重入的函数。
如果程序中存在协程泄漏问题,可以使用性能/调试/分析工具,如 pprof 和 Trace,来检查并找出泄漏的原因所在。