refactor to using runtime.Cleanup #15596
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What type of PR is this?
Other
Why
runtime.AddCleanup
?Go 1.23 introduced
runtime.AddCleanup
as a simpler, safer, and lower-overhead alternative toruntime.SetFinalizer
for cases where you just want to run some cleanup code when an object becomes unreachable.Problems with
runtime.SetFinalizer
Complex semantics –
SetFinalizer
allows the finalizer function to access the object’s memory, which means the GC must keep the object alive until the finalizer finishes. This can:Unpredictable execution –
Finalizers run at an unspecified time, possibly much later than the object becomes unreachable.
Misuse risk –
Because you can still read/write the object in the finalizer, people sometimes use it for logic that depends on object state — which is fragile and can break if GC behavior changes.
What
runtime.AddCleanup
does differentlyNo access to the object’s memory
When the cleanup function runs, the object has already been collected or is about to be collected. You can’t dereference it.
Lower runtime overhead
The GC doesn’t need to keep the object alive for the cleanup function, making cleanup cheaper.
Safer semantics
Because you can’t touch the object, there’s no risk of accidentally resurrecting it or depending on its state.
Intended purpose
It’s for releasing external resources (file descriptors, network connections, C handles, etc.) when an object is no longer used — not for inspecting object state.
Example
Here:
fd
value in the closure.*Resource
is unreachable.r
itself in the cleanup.Summary Table
SetFinalizer
AddCleanup
If you want, I can also give you a migration guide for turning your
SetFinalizer
-based code intoAddCleanup
-based code, with patterns for cases where you need to access object state.Do you want me to prepare that migration guide?
Which issues(s) does this PR fix?
Fixes #
Other notes for review
Acknowledgements