如果我有这样的程序,它会按预期失败(在 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
,它必须有一个 Read
和 Close
方法。但是 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 是安全的。
最佳答案
目前没有理由调用 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/