How to Use sync.Pool in Go for Efficient Object Reuse
In Go,
sync.Pool is used to cache and reuse temporary objects to reduce memory allocations and improve performance. You create a sync.Pool with a New function that provides new objects, then use Get() to retrieve and Put() to return objects to the pool.Syntax
The sync.Pool type provides a pool of temporary objects that can be reused to reduce memory allocations. It has two main methods: Get() to retrieve an object and Put(x interface{}) to return an object back to the pool. You initialize it with a New function that creates a new object when the pool is empty.
go
var pool = sync.Pool{ New: func() interface{} { return &MyType{} }, } obj := pool.Get().(*MyType) // Get an object from the pool // use obj pool.Put(obj) // Return the object to the pool
Example
This example shows how to use sync.Pool to reuse bytes.Buffer objects. It gets a buffer from the pool, writes a string, prints it, resets the buffer, and puts it back to the pool for reuse.
go
package main import ( "bytes" "fmt" "sync" ) func main() { var bufPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } // Get a buffer from the pool buf := bufPool.Get().(*bytes.Buffer) // Use the buffer buf.WriteString("Hello, sync.Pool!") fmt.Println(buf.String()) // Reset and put back to pool buf.Reset() bufPool.Put(buf) }
Output
Hello, sync.Pool!
Common Pitfalls
- Not resetting objects before putting back: Objects should be cleaned or reset before returning to the pool to avoid unexpected data reuse.
- Assuming objects stay in the pool: The pool may drop objects at any time, so always handle
Get()possibly returning a new object. - Using pool for long-lived objects:
sync.Poolis for short-lived temporary objects only, not for caching permanent data.
go
package main import ( "bytes" "fmt" "sync" ) func main() { var bufPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } // Wrong: Not resetting buffer before putting back buf := bufPool.Get().(*bytes.Buffer) buf.WriteString("Hello") fmt.Println(buf.String()) // Prints: Hello bufPool.Put(buf) // Buffer still has "Hello" // Next get will reuse buffer with old data buf2 := bufPool.Get().(*bytes.Buffer) fmt.Println(buf2.String()) // Prints: Hello (unexpected) // Right: Reset before putting back buf2.Reset() bufPool.Put(buf2) }
Output
Hello
Hello
Quick Reference
Remember these key points when using sync.Pool:
- Use
Newto define how new objects are created. - Always
Resetor clean objects beforePutto avoid stale data. Getmay return a new or reused object.- Ideal for short-lived, temporary objects to reduce GC pressure.
Key Takeaways
Use sync.Pool to efficiently reuse temporary objects and reduce memory allocations.
Always reset or clean objects before putting them back into the pool.
The pool may discard objects, so always handle new object creation in the New function.
sync.Pool is best suited for short-lived objects, not for caching long-term data.