如何写出内存泄露的程序?

Go语言语法简单,学习起来容易,也容易上手,所以越来越多的公司和个人采用Go语言开发应用程序。不管使用什么语言,内存泄露是经常遇到的一类问题,而使用Go语言编写内存泄露的代码却不容易,本文将教你几招编写出内存泄露的代码,以满足你创造出内存泄露bug的心里需求。

即使你编写出内存泄露的bug,一般来说也很容易通过pprof查找出来,或者通过pprof的两次对比中找出哪一块出现的问题,所以不要因为写出bug就沾沾自喜,此类bug还是很容易被发现的。

资源泄露

一些打开的资源,比如文件、数据库连接、TCP的连接,你如果忘记调用了它的Close方法,就会导致打开的文件描述符超过限制,或者底层的tcp连接不能被释放。

不去Close打开的文件

当你不再需要一个打开的文件,正常你需要调用它的Close方法,如果你不调用Close,就有可能文件描述符达到最大限制,无法在打开新的文件或者连接,程序会报too many open files的错误。

比如下面的例子,注释掉defer f.Close()后,你可以运行一下程序试试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main
import (
"log"
"os"
"strconv"
)
func main() {
for i := 0; i < 10240; i++ {
write("test.log", i)
}
}
func write(name string, data int) {
f, err := os.OpenFile(name, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
// defer f.Close()
if _, err := f.WriteString(strconv.Itoa(data) + "\n"); err != nil {
log.Fatal(err)
}
}

###

不调用 http.Response.Body.Close()

https://github.com/gocolly/colly/issues/321

字符串/slice

hanging goroutine

引用不在使用的对象

runtime.SetFinalizer误用

time.Ticker

defer