我只是在阅读/proc/diskstats
文件。我的代码是:
func ReadFromFile(filepath string)(string){
defer func() {
if err1 := recover(); err1 != nil {
fmt.Println("!!!!!!!!!!!!!!!!Panic Occured and Recovered in readFromFile(), Error Info: ", err1)
}
}()
strData := ""
data, err := ioutil.ReadFile(filepath)
if err != nil{
fmt.Println("File read error: ", err)
return ""
}
strData = string(data)
return strData
}
我得到的错误是:
File read error: open /proc/diskstats: too many open files
不仅对于这个文件,我对其他一些文件也有同样的错误。
我也运行了这个命令:
root@golang:~# lsof|wc -l
785
请指导我。
答案 0 :(得分:4)
基本上在UNIX平台中,操作系统限制了进程在任何给定时间可能具有的打开文件描述符的数量。
由于您已达到当前打开的文件(和/或管道或套接字)的限制并且您尝试打开新文件(或管道或插槽),因此引发错误too many open files
。
要避免此问题,必须在使用Close()
函数
答案 1 :(得分:4)
我遇到了同样的问题(可能是不同的情况或设置),并以不同的方式修复它。我创建了一个简单而简化的示例:
func some_func(file_name []string) {
for _, file_name := range file_names {
f, _ := os.Create(file_name)
// defer f.Close() // bad idea
_, _ = f.Write("some text")
f.Close() // better idea
}
}
这是一个坏主意,因为defer
将被执行,some_func
将返回,这可能需要一段时间 - 取决于循环大小。
答案 2 :(得分:1)
OP不提供Minimal, Reproducible Example。有问题的错误是由未发布的代码引起的。演示此问题的一种简单方法是仅在一个最小的示例中运行提供的代码(没有其他活动),并确保它不会失败。
函数ioutil.ReadFile
当然会关闭文件。在这种情况下,它的含义很简单,因为它试图在已经达到 的资源限制时打开新文件。
Go中常见的 gotcha 是无法关闭隐式打开的流。这种情况的一个特殊情况是,使用http
库的客户端功能时,将打开一个流。
客户端必须在完成响应后将其关闭:
resp, err := http.Get("http://example.com/")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
此类请求应始终包括使用上述表格的对Close
的调用。
可能还有其他类似的隐式流被打开的情况...
这是一个特别棘手的问题,因为对于琐碎的程序,您永远不会知道其中的区别。您需要经过数百或数千次迭代才能知道问题所在。然后,该错误通常可能表示为某些无关的函数调用的失败-正如OP所证明的那样。