Golang中打开文件错误过多

GKV*_*GKV 7 go

我只是在读取/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
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

File read error: open /proc/diskstats: too many open files
Run Code Online (Sandbox Code Playgroud)

不仅对于此文件,对于其他一些文件,我也遇到相同的错误。

我还运行了以下命令:

root@golang:~# lsof|wc -l

785
Run Code Online (Sandbox Code Playgroud)

请指导我。

Mic*_*ner 9

我遇到了相同的问题(可能是不同的情况或设置),并以不同的方式解决了它。我创建了一个简单的示例:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个坏主意,因为defer将被执行,何时some_func返回,这可能需要一段时间-取决于循环大小。

  • 惊人。感谢您的解决方案-像一个魅力。A ++ (2认同)

nob*_*bar 6

OP 不提供最小的、可重现的示例。有问题的错误是由未发布的代码引起的。一个简单的方法来证明这是简单地运行在一个小例子,所提供的代码(没有其他活动),并看到它并没有失败。

ioutil.ReadFile当然,函数关闭文件。在这种情况下,它被牵连,仅仅是因为它试图在已经达到资源限制时打开一个新文件。


Go 中的一个常见问题是无法关闭隐式打开的流。这种情况的一个特殊情况是在使用http库的客户端函数时打开了一个流。

例子:(1) , (2)

客户端必须在完成后关闭响应主体:

resp, err := http.Get("http://example.com/")
if err != nil {
    // handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
Run Code Online (Sandbox Code Playgroud)

此类请求应始终包括对 的调用Close,使用如上所示的形式。

可能还有其他类似的隐式流被打开的情况......


这是一个特别棘手的问题,因为对于琐碎的程序,您永远不会知道其中的区别。直到您通过数百或数千次迭代运行它,您才会知道存在问题。然后,错误可能经常表现为一些不相关的函数调用失败——正如 OP 所证明的那样。


Tin*_*wor 5

基本上在UNIX平台上,OS限制了进程在任何给定时间可能具有的打开文件描述符的数量。由于您已达到当前打开的文件(和/或管道或套接字)的限制,并且尝试打开新文件(和/或管道或套接字),因此引发了
错误too many open files
为避免此问题,您必须在使用Close()函数完成使用打开文件的操作后关闭文件

  • 不,在第54行有一个“ defer f.Close()”,导致文件从函数返回期间被关闭。如果Open调用失败,则会提早返回(以便不对未定义的值调用Close()方法)。 (2认同)