当前位置:  首页>> 技术小册>> GO面试指南

在 Go 中,如果不注意一些细节,就可能会导致协程泄露。常见的协程泄露情况包括:

在协程中使用了全局变量:如果协程中使用了全局变量,而这个全局变量在程序运行过程中没有被及时清理,那么这个协程就会一直等待全局变量被清理,从而导致协程泄露。

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. var (
  7. done chan bool = make(chan bool)
  8. )
  9. func main() {
  10. go func() {
  11. for {
  12. select {
  13. case <-done:
  14. fmt.Println("goroutine is done")
  15. return
  16. default:
  17. // 协程一直在等待 done 变量被关闭
  18. fmt.Println("goroutine is running")
  19. time.Sleep(100 * time.Millisecond)
  20. }
  21. }
  22. }()
  23. time.Sleep(1 * time.Second)
  24. // 没有关闭 done 变量,导致协程泄露
  25. }

在这个示例代码中,我们创建了一个全局的 done 变量,并在一个协程中使用它进行等待。如果在程序运行过程中没有及时关闭 done 变量,那么这个协程就会一直等待下去,从而导致协程泄露。

协程阻塞:如果一个协程在运行过程中一直阻塞,而没有其他协程来唤醒它,那么这个协程就会一直占用系统资源,从而导致协程泄露。

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func main() {
  7. go func() {
  8. // 协程一直在等待通道写入数据,而主 goroutine 没有向通道写入数据
  9. <-make(chan bool)
  10. }()
  11. time.Sleep(1 * time.Second)
  12. // 没有向通道写入数据,导致协程泄露
  13. }

在这个示例代码中,我们创建了一个协程并在其中使用通道进行阻塞等待。如果在程序运行过程中没有其他协程向通道写入数据,那么这个协程就会一直阻塞等待下去,从而导致协程泄露。

为避免协程泄露,需要注意及时清理协程使用的资源,以及避免协程的阻塞。在实际编程中,可以使用 sync.WaitGroup 来协调协程的启动和结束,从而避免协程泄露。


该分类下的相关小册推荐: