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

Rya*_*ach 5 garbage-collection go

我正在和一个朋友争论,讨论Go中可能浪费的资源。

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

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

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

Him*_*shu 3

Golang 编译器会处理无法访问的变量:-

存储位置确实对编写高效程序有影响。如果可能,Go 编译器将在该函数的堆栈帧中分配该函数的本地变量。但是,如果编译器无法证明函数返回后该变量未被引用,则编译器必须在垃圾收集堆上分配该变量以避免悬空指针错误。此外,如果局部变量非常大,将其存储在堆上而不是堆栈上可能更有意义。

虽然Golang包含垃圾收集。最好使用清理功能。您可以使用 defer 函数在函数结束时关闭文件。

defer f.close()
Run Code Online (Sandbox Code Playgroud)

查看SetFinalizer的文档以更好地了解这些概念:

func SetFinalizer(obj interface{}, finalizer interface{})
Run Code Online (Sandbox Code Playgroud)

SetFinalizer 将与 obj 关联的终结器设置为提供的终结器函数。当垃圾收集器发现具有关联终结器的不可访问块时,它会清除关联并在单独的 goroutine 中运行 Finalizer(obj)。这使得 obj 再次可访问,但现在没有关联的终结器。假设SetFinalizer不再被调用,下次垃圾收集器发现obj不可访问时,就会释放obj。

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