DEV Community

Cover image for Understanding Weak Pointers in Go
Walid LAGGOUNE
Walid LAGGOUNE

Posted on

Understanding Weak Pointers in Go

Hi, my name is Walid, a backend developer who’s currently learning Go and sharing my journey by writing about it along the way.


A weak pointer is a reference to an object that does not prevent the garbage collector (GC) from reclaiming the object. If there are no strong references to the object, the GC can collect it, and any weak pointers to it will automatically become nil

Why Use Weak Pointers?

Common use cases include:

  • Caching: Store objects without forcing them to remain in memory if they’re no longer used elsewhere.

  • Observer Patterns: Hold references to observers without preventing their garbage collection.

  • Canonicalization: Ensure only one instance of an object exists without preventing its collection when unused

  • Dependency Graphs: Prevent cycles in structures like trees or graphs.​

The weak Package in Go 1.24

Go 1.24 introduces the weak package, providing a straightforward API for creating and using weak pointers.​

import "weak"

type MyStruct struct {
    Data string
}

func main() {
    obj := &MyStruct{Data: "example"}
    wp := weak.Make(obj) // Create a weak pointer
    val := wp.Value()    // Retrieve the strong pointer or nil
    if val != nil {
        fmt.Println(val.Data)
    } else {
        fmt.Println("Object has been garbage collected")
    }
}

Enter fullscreen mode Exit fullscreen mode

In this example, weak.Make(obj) creates a weak pointer to obj. Calling wp.Value() returns the strong pointer if the object is still alive or nil if it has been collected.

Practical Example: Implementing a Cache

One practical application of weak pointers is in building caches that don't prevent their entries from being garbage collected.​

import (
    "sync"
    "weak"
)

type Data struct {
    Value string
}

var cache sync.Map // map[string]weak.Pointer[*Data]

func GetData(key string) *Data {
    if wp, ok := cache.Load(key); ok {
        if data := wp.(weak.Pointer[*Data]).Value(); data != nil {
            return data
        }
    }
    // Load data from source
    data := &Data{Value: "fresh data"}
    cache.Store(key, weak.Make(data))
    return data
}

Enter fullscreen mode Exit fullscreen mode

In this cache implementation, entries are stored as weak pointers. If no other strong references to the data exist, the GC can collect it, and subsequent calls to GetData will reload the data

Testing Weak Pointers

import (
    "fmt"
    "runtime"
    "weak"
)

type MyStruct struct {
    Data string
}

func main() {
    obj := &MyStruct{Data: "test"}
    wp := weak.Make(obj)
    obj = nil // Remove strong reference
    runtime.GC()
    if wp.Value() == nil {
        fmt.Println("Object has been garbage collected")
    } else {
        fmt.Println("Object is still alive")
    }
}

Enter fullscreen mode Exit fullscreen mode

Warp.dev image

Warp is the highest-rated coding agent—proven by benchmarks.

Warp outperforms every other coding agent on the market, and gives you full control over which model you use. Get started now for free, or upgrade and unlock 2.5x AI credits on Warp's paid plans.

Download Warp

Top comments (0)

Gen AI apps are built with MongoDB Atlas

Gen AI apps are built with MongoDB Atlas

MongoDB Atlas is the developer-friendly database for building, scaling, and running gen AI & LLM apps—no separate vector DB needed. Enjoy native vector search, 115+ regions, and flexible document modeling. Build AI faster, all in one place.

Start Free

👋 Kindness is contagious

Explore this insightful write-up, celebrated by our thriving DEV Community. Developers everywhere are invited to contribute and elevate our shared expertise.

A simple "thank you" can brighten someone’s day—leave your appreciation in the comments!

On DEV, knowledge-sharing fuels our progress and strengthens our community ties. Found this useful? A quick thank you to the author makes all the difference.

Okay