Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go &引用;“打开的文件太多”;使用os.Create_Go - Fatal编程技术网

Go &引用;“打开的文件太多”;使用os.Create

Go &引用;“打开的文件太多”;使用os.Create,go,Go,我有大约22万个图像文件(.png)要创建。我在尝试创建第1'081个文件时遇到此错误消息: 死机:打开/media/Snaps/pics/image1081_0.png:打开的文件太多 我添加了defer w.Close()行,但它没有更改错误 i := 1 for i <= 223129 { (some other code to prepare the data and create the chart) img := vgimg.New(450,

我有大约22万个图像文件(.png)要创建。我在尝试创建第1'081个文件时遇到此错误消息: 死机:打开
/media/Snaps/pics/image1081_0.png:打开的文件太多

我添加了defer w.Close()行,但它没有更改错误

    i := 1
    for i <= 223129 {

    (some other code to prepare the data and create the chart)

    img := vgimg.New(450, 600)
    dc := draw.New(img)

    canvases := table.Align(plots, dc)
    plots[0][0].Draw(canvases[0][0])
    plots[1][0].Draw(canvases[1][0])
    plots[2][0].Draw(canvases[2][0])


    testFile := "/media/Snaps/pics/image"+strconv.Itoa(i+60)+"_"+gain_loss+".png"

        w, err := os.Create(testFile)
        if err != nil {
            panic(err)
        }
        defer w.Close()

        png := vgimg.PngCanvas{Canvas: img}
        if _, err := png.WriteTo(w); err != nil {
            panic(err)
        }   

        //move to next image
        i = i + 1
     }
i:=1

对于iok,我得到了它,将
defer w.Close()
更改为
w.Close()
,然后将其移动到后面

png := vgimg.PngCanvas{Canvas: img}
if _, err := png.WriteTo(w); err != nil {
      panic(err)
}
我现在超过10000张图片,正在运行

“defer”语句调用其执行被延迟到的函数 由于 函数执行了一个return语句,到达 它的函数体,或者因为相应的goroutine是 惊慌失措

DeferStmt = "defer" Expression .
表达式必须是函数或方法调用;不可能 括号内。对于,对内置函数的调用受到限制 表达式语句

每次执行“defer”语句时,函数值和 调用的参数按常规计算并重新保存,但 未调用实际函数。相反,延迟函数是 在周围函数返回之前立即调用,在 相反,他们被推迟了。如果是延迟函数值 计算结果为nil,在调用函数时执行恐慌,而不是 当执行“defer”语句时


换句话说,如果在循环中处理文件,请将单个文件的处理放在单独的函数中,以将
Open
defer Close()配对。这避免了“打开的文件太多”错误

例如,使用这样的文件处理结构来保证每个文件在使用后立即关闭

package main

import (
    "fmt"
    "io/ioutil"
    "os"
)

// process single file
func processFile(name string) error {
    f, err := os.Open(name)
    if err != nil {
        return err
    }
    defer f.Close()
    fi, err := f.Stat()
    if err != nil {
        return err
    }
    fmt.Println(fi.Name(), fi.Size())
    return nil
}

func main() {
    wd, err := os.Getwd()
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }
    fis, err := ioutil.ReadDir(wd)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }
    // process all files
    for _, fi := range fis {
        processFile(fi.Name())
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
        }
    }
}
游乐场:

输出:

dev 1644
etc 1644
tmp 548
usr 822

延迟语句在周围函数返回之前不会执行,这就是为什么文件在for循环之后才保持打开状态

要解决此问题,只需在循环中插入匿名函数调用:

for ... {
    func() {
        w, err := os.Create(testFile)
        if err != nil {
            panic(err)
        }
        defer w.Close()
        ...
    }()
}

这样,在循环的每次迭代之后,当前文件都将关闭。

如果使用
延迟
,则循环中的文件将无法工作。提供的代码不足以检查它。我已经添加了循环的开头。我应该将defer移到循环之外吗?
defer
在函数返回时执行,并且在函数返回之前您将用完FD。你不能在循环外延迟(你会怎么做?),你需要关闭循环中的文件。请看,您可以将body循环移动到一个函数中,在该函数中,您可以使用原始代码中提供的defer。如果使用内联函数,请注意变量阴影(),如果之前有任何错误。关闭()文件,将不会调用Close。这就是为什么在类型上使用“延迟”来关闭事物。在您的情况下,我将简单地在循环中添加对匿名func的调用。