直接回答:Go 里有 GC 不等于什么都不用管:os.File、net.Conn、http.Response.Body、sql.Rows、sql.DB 这些都必须显式 Close,否则会句柄泄漏,最终把进程拖死。
在 Go 语言中,有一些资源需要在使用完后手动释放,以避免资源泄漏和浪费,具体来说包括:
- 文件句柄(*os.File):文件对象需要在使用完后调用Close()方法手动关闭,以避免因资源泄漏而导致系统文件句柄数量达到上限。
1 2 3 4 5
| f, err := os.Open("file.txt") if err != nil { } defer f.Close()
|
- 网络连接(net.Conn):网络连接需要在使用完后调用Close()方法手动关闭,以避免因连接过多而占用过多系统资源。
1 2 3 4 5
| conn, err := net.Dial("tcp", "address") if err != nil { } defer conn.Close()
|
- 通道(channel):当通道不再需要时,需要显式地将其关闭以避免其阻塞 goroutine。
- 定时器(time.Timer):定时器需要手动停止(stop),否则可能会在 goroutine 关闭时导致死锁或泄漏。
1 2
| timer := time.NewTimer(time.Second * 5) defer timer.Stop()
|
- SQL(database/sql.DB和database/sql.Tx):数据库连接需要在使用完后调用Close()方法手动关闭,以避免因连接过多而占用过多系统资源(如果有连接池的情况下,使用完后返回连接池就好了,不需要手动关闭)。
- HTTP请求得到响应后,需要调用响应体的 Close() 方法来手动关闭所关联的数据流以释放相应的系统资源。
1 2 3 4 5
| resp, err := http.Get("http://www.example.com/") if err != nil { } defer resp.Body.Close()
|
Go语言中大多数资源都会自动释放,但一些资源仍需要手动释放以确保程序的效率和稳定性。因此,要时刻谨记在使用完相关资源后要调用相应的释放方法。
这篇笔记整理自我自己的实践记录,如果做法有出入,或者你踩过别的坑,欢迎到留言板一起聊聊。