Go内存泄漏
示例1
package main import ( "fmt" "runtime" "time" ) func GetData() { var ch chan struct{} <-ch } func main() { defer func() { fmt.Println("goroutines: ", runtime.NumGoroutine()) }() GetData() time.Sleep(2 * time.Second) }
输出会不会抛异常?为什么?看下输出结果:
原因是chan未初始化,未初始化的chan要去消费,肯定fatal。看chan消费源码:
那怎么去解决这个问题呢?看示例2
示例2
package main import ( "fmt" "runtime" "time" ) func GetData() { var ch chan struct{} go func() { <-ch }() } func main() { defer func() { fmt.Println("goroutines: ", runtime.NumGoroutine()) }() GetData() time.Sleep(2 * time.Second) }
输出是什么?为什么?看下结果:
原因是把异常错误代码go出去了,不会影响到主goroutine的逻辑。
到这里你以为会万事大吉,准备上线了。上线之后不到one hour服务宕机了,你百思不得其解,问题出在哪里呢?
朋友们,出题就出在goroutine消费的是一个nil的chan,它一直阻塞在那里,你开辟的goroutine越多,泄漏的越多,导致内存耗尽触发OOM。
小结
可能朋友们觉得我只管写代码,泄漏等上完线再说吧,反正本地也验证不出来,你错了goleak
专门用来排查goroutine泄漏的,用起来吧。
github地址:https://github.com/uber-go/goleak