Previously, I wrote an article about the runtime.SetFinalizer that is used to be called when an object is cleaned up, but some issues with this function cause it to be used less frequently.
https://github.com/golang/go/issues/67535
SetFinalizermust always refer to the first word of an allocation. This means programmers must know what an ‘allocation’ is, whereas that distinction isn’t generally exposed in the language.- There cannot be more than one finalizer on any object.
- Objects with finalizers involved in any reference cycle will silently fail to be freed, and the finalizer will never run.
- Objects with finalizers require at least two GC cycles to be freed.
For the above reasons, a new function runtime.AddCleanUp has been added in Golang 1.24 to replace runtime.SetFinalizer.
Neither runtime.AddCleanup nor runtime.SetFinalizer is guaranteed to execute.
The design goal of AddCleanup is to address many of the problems with runtime.SetFinalizer, in particular avoids object resurrection, thus allowing for the timely cleanup of objects, and supporting cyclic cleanup of objects.
API
|  |  | 
Based on this, a Demo for RAII (Resource Acquisition Is Initialization) can be written. In the go weak article, we implemented a fixed-length cache, changed the code a bit, add a  newElemWeak method that automatically calls delete to remove the key from the cache when the oldest elem is evicted. We don’t need to manage it manually.
|  |  | 
A Few Things to Keep in Mind
AddCleanup places a few constraints on ptr and supports attaching multiple cleanup functions to the same pointer. However, if ptr is reachable from cleanup or arg, it will never be reclaimed (memory leak), and the cleanup function will never run. For the moment, this scenario doesn’t pan out. However, a pattern like GODEBUG=gccheckmark=1 may detect this in the future.
For example
https://gist.github.com/hxzhouh/5bb1d55259dcb4dab87b37beaef9bea2
fmt.Println("close f") will not be printed, and the file will not be closed.
When binding multiple cleanups to a single ptr, its running order may be variable since cleanup runs in a separate goroutine.
In particular, if several objects point to each other and become unreachable simultaneously, their cleanup functions can all be run and in any order. This is true even if the objects form a loop (runtime.SetFinalizer creates a memory leak in this case).
for example
https://gist.github.com/hxzhouh/ca402c723faa78726baba7e56bff573a
