sync.Pool was introduced in Go for the reuse of temporary objects and to reduce pressure on the garbage collector. Historically, developers created their own object pools using mutexes, but this led to complex code and potential synchronization errors. sync.Pool is a thread-safe structure from the standard library designed to produce an object upon first access, store it, and subsequently return that object to the pool for reuse.
The problem is that with a large number of short-lived objects (e.g., buffers in an HTTP server), the system often spends a lot of time on allocations. Using sync.Pool allows for optional caching of objects without guaranteeing their retention in memory, but improving performance by reducing the number of garbage collections.
The solution is to use Pool for temporary, homogeneous, quickly reusable structures (e.g., bytes.Buffer), returning the object to the pool with Put and retrieving it with Get. Objects can be removed from the pool at any time (e.g., during GC), so it is not suitable for long-term storage.
Example code:
import ( "sync" "bytes" "fmt" ) var bufPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } func main() { b := bufPool.Get().(*bytes.Buffer) b.Reset() b.WriteString("hello, world!") fmt.Println(b.String()) bufPool.Put(b) // be sure to return }
Key features:
Can sync.Pool be used for long-term storage of state?
No, any objects in Pool can be reclaimed by the system at any moment (during GC or load reduction). Pool is intended only for temporary storage between goroutines.
Does Pool guarantee the return of exactly the same object that was previously put in?
No. Pool returns any suitable object or creates a new one if necessary. One should not maintain a binding between user and Pool object.
Should the object be cleared/reset before returning to Pool?
Yes, otherwise the next thread may receive a "dirty" object with remnants of previous data.
Negative case
A developer saves client states in Pool for reconnections to chat. After GC runs, connections disappear, and users lose data.
Pros:
Cons:
Positive case
Buffer objects for marshal/unmarshal JSON are kept in Pool and used for batch processing of messages. After processing, objects are cleared and returned to the pool, reducing the number of allocations.
Pros:
Cons: