5 ms·
> AFK right now, but files opened with os.Open will be automatically closed once all its references have been collected. No, they're not. The idiomatic usage i
by majewsky 3y ago
> AFK right now, but files opened with os.Open will be automatically closed once all its references have been collected.
No, they're not. The idiomatic usage is to defer a Close() call after checking that Open succeeded, like so:
file, err := os.Open("/etc/hostname")
if err != nil {
doSomethingWith(err)
}
defer file.Close()
doSomethingWith(file)
But you'd be forgiven for not knowing that: To my own surprise, I could not find the need for this idiom explained in the package documentation for os.Open, though you can see it in action throughout the std implementation. For example: https://cs.opensource.google/go/go/+/refs/tags/go1.20.4:src/os/file.go;l=674 https://cs.opensource.google/go/go/+/refs/tags/go1.20.4:src/...
- javierhonduco 3y agoFWIW, I never advocated for not explicitly calling Close(). Brought up the finalizer in File, because it seems to have performance implications and it’s called for every file handle. From the docs (https://pkg.go.dev/os#File.Fd https://pkg.go.dev/os#File.Fd): > Fd returns the integer Unix file descriptor referencing the open file. If f is closed, the file descriptor becomes invalid. If f is garbage collected, a finalizer may close the file descriptor, making it invalid; see runtime.SetFinalizer for more information on when a finalizer might be run. To give more context on how I found this out, we were missing a Close for a couple of files in our codebase. As soon as I realised I added them, but checked in production for file descriptor leaks and there were none. Checking Go’s source code led me to the finalizer and this doc confirmed what I saw in the code.