Finalization in Go: Default Objects and Pitfalls
In Go, finalization is the process of performing cleanup actions on objects before they are garbage collected. By default, only a select few types of objects are finalized. This includes:
While finalization provides a convenient way to perform cleanup actions, it also comes with potential pitfalls. One such issue arises when an os.File is created using os.NewFile(fd int, name string) *File and the same file descriptor is used by another os.File object. In this scenario, garbage collecting either of the file objects will render the other unusable.
For example, consider the following code:
package main import ( "fmt" "os" "runtime" ) func open() { os.NewFile(1, "stdout") } func main() { open() // Force finalization of unreachable objects _ = make([]byte, 1e7) runtime.GC() _, err := fmt.Println("some text") // Print something via os.Stdout if err != nil { fmt.Fprintln(os.Stderr, "could not print the text") } }
This code will print "could not print the text" because the garbage collection of one os.File object (created by os.NewFile) closes the file descriptor, which is also used by the other os.File object (os.Stdout). As a result, os.Stdout becomes unusable for further I/O operations.
To avoid this pitfall, it's important to carefully manage file descriptors, particularly when using os.NewFile. Alternatively, one can disable finalization for os.File objects by setting their finalizers to nil using the runtime.SetFinalizer function.
The above is the detailed content of Go Finalization: What are the Pitfalls and How Can They Be Avoided?. For more information, please follow other related articles on the PHP Chinese website!