Consider the following code snippet:
func a(fd int) {
file := os.NewFile(uintptr(fd), "")
defer func() {
if err := file.Close(); err != nil {
fmt.Printf("%v", err)
}
}
This piece of code is legit, and will work OK. Files will be closed upon returning from a()
However, The following will not work correctly:
func a(fd int) {
file := os.NewFile(uintptr(fd), "")
defer func() {
if err := syscall.Close(int(file.Fd()); err != nil {
fmt.Printf("%v", err)
}
}
The error that will be received, occasionally, will be bad file descriptor
, due to the fact of NewFile setting a finalizer
which, during garbage collection, will close the file itself.
Whats unclear to me, is that the deferred function still has a reference to the file, so theoretically, it shouldn't be garbage collected yet. So why is golang runtime behaves that way?