What are weak pointers in Go and when would you use them?
Go 1.24 added the weak package. weak.Make(p) returns a weak.Pointer[T] that does not keep *p alive. wp.Value() returns the original pointer, or nil once the object has been collected. Two weak pointers made from the same object compare equal, even after it is collected, so they work as map keys. Typical uses are canonicalisation (interning) caches and side tables keyed by an object, where an entry should not by itself keep the object alive.
type Cache[K comparable, V any] struct {
mu sync.Mutex
m map[K]weak.Pointer[V]
}
func NewCache[K comparable, V any]() *Cache[K, V] {
return &Cache[K, V]{m: make(map[K]weak.Pointer[V])}
}
func (c *Cache[K, V]) Get(k K, load func() *V) *V {
c.mu.Lock()
defer c.mu.Unlock()
if wp, ok := c.m[k]; ok {
if v := wp.Value(); v != nil {
return v // still alive somewhere: reuse it
}
}
v := load()
c.m[k] = weak.Make(v)
// Remove the stale entry once v is collected (closure captures c and k, not v).
runtime.AddCleanup(v, func(k K) {
c.mu.Lock()
defer c.mu.Unlock()
if wp, ok := c.m[k]; ok && wp.Value() == nil {
delete(c.m, k)
}
}, k)
return v
}
For interning comparable values, you do not need to build this yourself: the unique package (Go 1.23) provides unique.Make(v), which returns a unique.Handle[T]. Handles compare in O(1) with a pointer comparison and are released automatically, using the same weak mechanism internally.
Gotcha: weak pointers are not a caching policy. An entry disappears as soon as the last strong reference goes, which may be almost immediately. For an LRU or TTL cache you still need strong references.
More on Memory, GC & Runtime Internals
- Q354What does this program print? Explain how finalizers behave.
- Q355What is
runtime.AddCleanupand why is it preferred overSetFinalizer? - Q357What does
runtime.KeepAlivedo and when is it required? - Q358What does this print, and what memory problem does it illustrate?
- Q359Why can removing elements from a slice of pointers leak memory?
- Q360Do Go maps shrink after you delete entries? How do you reclaim the memory?