> ## Content Index
> Fetch the complete content index at: https://huizhou92.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Golang 1.24: runtime.AddCleanup
- URL: https://huizhou92.com/golang-1-24-runtime-addcleanup/
- Published: 2024-12-17T10:37:49.000Z
- Updated: 2026-09-08T02:29:47.000Z
- Author: huizhou92
- Tags: tech, go1_24, golang, #lang-en

Previously, I wrote an [article](https://huizhou92.com/content/files/2026/09/decrypt-go-runtime-setfinalizer-adf19cb5fdcb-1.html) 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](https://github.com/golang/go/issues/67535?ref=huizhou92.com)
> 
> - `SetFinalizer` must 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

```go
func AddCleanup[T, S any](ptr *T, cleanup func(S), arg S) Cleanup

```

Based on this, a Demo for RAII (Resource Acquisition Is Initialization) can be written. In the [go weak](https://huizhou92.com/content/files/2026/09/go1-24-new-std-lib-weak-6e0a79a27902-1.html) 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.

```go
func (c *WeakCache) newElemWeak(elem *list.Element) weak.Pointer[list.Element] {
	elemWeak := weak.Make(elem)
	runtime.AddCleanup(elem, func(name string) {
		delete(c.cache, name)
	}, elem.Value.(*CacheItem).key)
	return elemWeak
}

```

## 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](https://gist.github.com/hxzhouh/5bb1d55259dcb4dab87b37beaef9bea2?ref=huizhou92.com)  
[View code snippet on GitHub Gist →](https://gist.github.com/hxzhouh/5bb1d55259dcb4dab87b37beaef9bea2?ref=huizhou92.com)  
`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](https://gist.github.com/hxzhouh/ca402c723faa78726baba7e56bff573a?ref=huizhou92.com)  
[View code snippet on GitHub Gist →](https://gist.github.com/hxzhouh/ca402c723faa78726baba7e56bff573a?ref=huizhou92.com)

## References

1. [https://github.com/golang/go/issues/67535](https://github.com/golang/go/issues/67535?ref=huizhou92.com)