注意:部分内容摘自 深入探讨 goroutine 泄漏和避免它们的最佳实践 - 知乎
1、goroutine泄漏的产生
// 例1
func newgoroutine(dataChan chan <dataType>) {
data := makeNetworkCall()
dataChan <- data // 阻塞住了
return
}
func main() {
dataChan := make(chan <dataType>)
go newgoroutine(dataChan)
return
}
// 例2
func newgoroutine(dataChan chan <dataType>) {
data := <- dataChan // 阻塞住了
return
}
func main() {
dataChan := make(chan <dataType>)
go newgoroutine(dataChan)
data, err := makeNetworkCall()
if err != nil {
return
}
dataChan <- data
return
}
2、发现
(1)通过goroutin监控
(2)服务器启动时使用禁用垃圾收集器 debug.SetGCPercent(-1),然后
在运行代码中打印 API
启动前和执行后正在运行的 goroutines
的数量,如果服务在前后返回不同数量的 Goroutines
,那么该流程中存在泄漏。
func ApplyPromo() {
fmt.Println(runtime.NumGoroutine())
defer fmt.Println(runtime.NumGoroutine()
}
3、避免
例如为避免上面两个case,可以将无缓冲区的channel改为有缓冲区的channel。