是否需要关闭zip.NewReader(bytes.NewReader(),len)或自动垃圾回收?

时间:2018-07-10 09:02:21

标签: go garbage-collection

我正在和朋友吵架,讨论Go中可能浪费的资源。

如果Reader在内存中的字节数组上运行,是否必须关闭Reader?

func readJar(zipBytes []byte, readMeta bool) (m jar.Manifest, err error) {
    reader, err := zip.NewReader(bytes.NewReader(zipBytes), int64(len(zipBytes)))
    if err != nil {
        return
    }

    for _, file := range reader.File {
        switch file.Name {
        case jar.ManifestPath:
            m, err = readManifest(file)
            if err != nil {
                return
            }
        }
    }
    return
}

func readManifest(file *zip.File) (jar.Manifest, error) {
    reader, err := file.Open()
    if err != nil {
        return nil, err
    }

    defer reader.Close()
    return jar.ReadManifest(reader)
}

最初它被认为是文件句柄泄漏的来源,但其他原因也应归咎于此。

此泄漏内存还是Go可以进行足够的转义分析/垃圾回收?

1 个答案:

答案 0 :(得分:2)

Golang编译器负责unreachable variables:-

  

存储位置确实会影响写入效率   程式。如果可能,Go编译器将分配变量   对于该函数的堆栈框架中的某个函数而言是本地的。但是,如果   编译器无法证明之后没有引用该变量   函数返回,则编译器必须在   垃圾回收堆,以避免悬空的指针错误。另外,如果   局部变量很大,将其存储可能更有意义   在堆而不是堆栈上。

尽管Golang包含垃圾回收。最好使用清理功能。您可以使用defer函数在函数末尾关闭文件。

defer f.close()

查看SetFinalizer的文档以对这些概念有更多的了解:

func SetFinalizer(obj interface{}, finalizer interface{})
  

SetFinalizer将与obj关联的终结器设置为所提供的   终结函数。当垃圾收集器发现无法访问时   用关联的终结器阻止,清除关联并运行   finalizer(obj)在单独的goroutine中。这使得obj可达   再次,但是现在没有关联的终结器。假如说   下次没有垃圾回收器时,不会再次调用SetFinalizer   看到obj无法访问,它将释放obj。

终结器运行一个对象,以检查它是否无法从源到达。它可以用于文件描述符,但是依靠终结器来刷新内存中的I / O缓冲区(例如bufio.Writer)将是一个错误,因为该缓冲区不会在程序退出时被刷新。