If I have a program like this, it fails as expected (on 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)
}
However this program succeeds:
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")
}
even though I did not close the gzip reader. My question is: what is the point of closing the gzip reader? What "bad" can happen if you don't do it? I thought one possible reason was http#Response.Body [1], because if a response contains Content-Encoding: gzip, then Go will automatically wrap the Body in a gzip.Reader. If that was the case, then a Close method would be required, as Body being a io.ReadCloser, it must have a Read and Close method. However gzip#Reader.Close specifically says that it doesn't close the
underlying reader:
Close closes the Reader. It does not close the underlying io.Reader.
So wrapping Body with gzip Reader directly would be bad, because the Body would be left open on Close. The source code confirms that they use a custom gzip type instead [2]. Interestingly, the Close method on this type [3] closes the underlying reader, but doesn't bother to close the gzip reader, even using defer. So I think it can be safe to omit using gzip Reader Close in the general case.