file - gzip Reader.Close 的意义何在?

标签 file go gzip

如果我有这样的程序,它会按预期失败(在 Windows 上):

package main

import (
   "fmt"
   "os"
)

func main() {
   old := "go1.16.5.src.tar.gz"
   os.Open(old)
   err := os.Rename(old, "new.tar.gz")
   // The process cannot access the file because it is being used by another process.
   fmt.Println(err)
}

但是这个程序成功了:

package main

import (
   "compress/gzip"
   "os"
)

func main() {
   old := "go1.16.5.src.tar.gz"
   f, err := os.Open(old)
   if err != nil {
      panic(err)
   }
   gzip.NewReader(f)
   f.Close()
   os.Rename(old, "new.tar.gz")
}

即使我没有关闭 gzip 阅读器。我的问题是:关闭 gzip 阅读器有什么意义?如果你不这样做,会发生什么“坏事”?我认为一个可能的原因是 http#Response.Body [1],因为如果响应包含 Content-Encoding: gzip,那么 Go 会自动将 Body 包装在 gzip.Reader。如果是这种情况,那么就需要一个 Close 方法,因为 Body 是一个 io.ReadCloser,它必须有一个 ReadClose方法。但是 gzip#Reader.Close 明确表示它不会关闭 潜在读者:

Close closes the Reader. It does not close the underlying io.Reader.

所以直接用 gzip Reader 包装 Body 会很糟糕,因为在 Close 时 Body 会保持打开状态。源代码确认他们使用自定义 gzip 类型来代替 [2]。有趣的是,这种类型 [3] 上的 Close 方法会关闭底层阅读器,但不会费心关闭 gzip 阅读器,即使使用 defer 也是如此。所以我认为在一般情况下省略使用 gzip Reader Close 是安全的。

  1. https://golang.org/pkg/net/http#Response.Body
  2. https://github.com/golang/go/blob/go1.16.5/src/net/http/transport.go#L2187
  3. https://github.com/golang/go/blob/go1.16.5/src/net/http/transport.go#L2831-L2833

最佳答案

目前没有理由调用 Close(),但将来可能会改变。

Close() 方法最初是用来拆除 deflater 使用的后台 goroutine。后台 goroutine 在 a June, 2011 change list 中被移除.

CL的作者写了以下in a comment on the CL :

Close used to tear down the goroutine associated with the reader, but now there isn't one. Probably Close will go away entirely, but that's a separate CL.

他们从来没有在 compatibility guarantee 之前删除 Close() 方法。在 Go 1 版本中引入。

As of June, 2020该方法实际上并没有做任何事情。 Close() 方法会返回解压缩器遇到的任何错误。当应用程序读取到流的末尾时,Read() 也会返回错误,因此无需调用 Close() 来获取错误。

关于file - gzip Reader.Close 的意义何在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68074107/

相关文章:

file - Go中如何一步返回hash和bytes?

interface - 鸭子类型(duck typing)在 Go 中打字

gzip - 如何从损坏的 .tar.gz 存档中恢复文件?

nginx - 替换来自代理的压缩响应中的文本

javascript - Ajax 调用获取远程文件仅返回文件的一部分

c - 在 C : Reading integers from a file

file - 使用 GWT 列出目录中的文件

c - 在文件读取中添加 null 的位置

hadoop - 如何在 gzip 文件上使用 CombineFileInputFormat?

multithreading - 自同步 Goroutines 以死锁告终