我试图检测 Go 打开的文件描述,但不要故意关闭。换句话说,我试图让我的代码“错误”,导致资源泄漏。
我的代码是
func hh(w http.ResponseWriter, r *http.Request) {
f0, err := os.OpenFile("notes.txt", os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
log.Fatal(err)
}
// I don't close file
fmt.Println(io.ReadAll(f0))
}
func main() {
http.HandleFunc("/req", hh)
log.Fatal(http.ListenAndServe(":8080", nil))
}
我使用 shell 脚本文件 FCOUNT=`lsof -p $1 | grep -v " txt " | wc -l`;echo "PID: $1 $FCOUNT" | sort -nk3
打印出有多少文件描述属于这个 Go 程序。
无论我向此服务器 (curl http://localhost:8080/req
) 发送多少个请求,我的 MacBook 上的数字仍然是 10。当然,我与 Activity Monitor
核对并得到相同的答案。
PS:我的第一个版本的代码实际上使用了 http.Get
并且没有关闭响应 Body
。也有同样的情况。
我的环境:macOS Big Sur 11.2.3
,go version go1.16.2 darwin/amd64
有谁知道为什么文件描述编号在我认为应该泄漏时仍然保持不变?我的shell脚本错了吗?还是 Golang 里面有什么花样?
谢谢!
更新
问题是我正在检查名为 go
的进程而不是我的文件夹名称。 Go 真的给了我一个额外的 go
程序,看起来像一个守护进程,它不能显示 fd 细节。真实的程序清楚地显示了 fd 泄漏。尽管如此,我还是从有关 golang GC 的答案和评论中获得了一些知识。
我要结束这个问题。
答案 0 :(得分:1)
在 Unix 中,打开的文件被垃圾收集器关闭:
答案 1 :(得分:1)
作为 Burak Serdar notes,打开的文件可能在 gc 期间被关闭。这意味着对主题行中提出的问题的答案——“在某些情况下 Go 会自动关闭文件描述吗?”——是“是”。但是在某些情况下这里做了很多繁重的工作。
垃圾收集实际发生的时间点通常很难预测(尽管您可以有意地自己调用 GC 代码)。终结器运行的时间点甚至更难预测,因为某些工作可能在单独的 goroutine 中完成。有关详细信息,请参阅 How to stop the golang gc and trigger it manually?,并注意 Go 的每个版本可能会更改有关 GC 内部的一些规则(尽管 GOGC
的操作非常稳定)。