Improved Finalization in Go 1.24: Introducing runtime.AddCleanup
Go 1.24 introduces a significant improvement in how Go handles finalization and resource clean-up with the new runtime.AddCleanup function…
Go 1.24 introduces a significant improvement in how Go handles finalization and resource clean-up with the new runtime.AddCleanup function…
Improved Finalization in Go 1.24: Introducing runtime.AddCleanup
Go 1.24 introduces a significant improvement in how Go handles finalization and resource clean-up with the new runtime.AddCleanup function. This new mechanism provides a more efficient and flexible way to perform clean-up actions compared to the traditional runtime.SetFinalizer.
Why runtime.AddCleanup?
Finalizers in Go are used to run clean-up code when an object becomes unreachable, helping to release system resources such as file handles and network connections. However, runtime.SetFinalizer has several limitations:
- Unpredictable Execution: The execution of finalizers depends on garbage collection, which is non-deterministic.
- Risk of Memory Leaks: Objects with finalizers may be kept alive longer than necessary.
- Difficulty Handling Cyclic References: When objects reference each other, finalization may not trigger as expected.
To address these issues, Go 1.24 introduces runtime.AddCleanup, offering a more structured and predictable approach to resource clean-up.
Using runtime.AddCleanup
Basic Example
Here’s how runtime.AddCleanup can be used to register clean-up functions:
package main
import (
"database/sql"
"fmt"
"runtime"
"github.com/DATA-DOG/go-sqlmock"
)
type Resource struct {
db *sql.DB
}
func NewResource() *Resource {
db, _, _ := sqlmock.New()
res := &Resource{db: db}
runtime.AddCleanup(res, func(db *sql.DB) {
fmt.Println("Closing DB connection")
_ = db.Close()
}, res.db)
return res
}
func main() {
res := NewResource()
_ = res
res = nil
runtime.GC()
}Key Advantages
- Multiple Clean-up Functions: Unlike
runtime.SetFinalizer, multiple clean-up functions can be attached to a single object. - Handles Cyclic References: Works better in cases where objects form reference cycles.
- Does Not Delay Object Deallocation: Clean-up is handled more efficiently without prolonging the object’s lifetime unnecessarily.
Comparison with runtime.SetFinalizer
| Feature | runtime.SetFinalizer | runtime.AddCleanup |
|---|---|---|
| Execution Timing | Non-deterministic, tied to GC More predictable | Multiple Cleanups Not supported Supported |
| Handles Cycles | No | Yes |
| Memory Efficiency | Can delay object collection | More efficient |
Use Cases for runtime.AddCleanup
- Managing File and Network Handles: Ensuring files and connections are closed properly.
- Preventing Memory Leaks: Efficient clean-up of in-memory caches and temporary objects.
- More Reliable Finalization: Providing a structured approach to cleaning up resources.
Conclusion
The introduction of runtime.AddCleanup in Go 1.24 enhances the way finalization works, addressing key limitations of runtime.SetFinalizer. It provides a more predictable, flexible, and efficient way to manage resource clean-up.
Stay tuned for the next post, where we explore the new weak package and how it enables weak pointers for more memory-efficient applications.