Golang / Golang Internals and Memory Management Interview Questions
What is sync.Pool and when should you use it?
sync.Pool is a thread-safe pool of temporarily reusable objects. It reduces GC pressure by allowing objects to be returned to the pool after use and reused by the next caller, avoiding repeated heap allocation and deallocation.
// Typical use: expensive-to-allocate, frequently used objects var bufPool = sync.Pool{ New: func() any { // Called when pool is empty â allocate a fresh object buf := make([]byte, 0, 4096) return &buf }, } func processRequest(data []byte) string { // Get a buffer from the pool (may be a fresh allocation or reused) bufPtr := bufPool.Get().(*[]byte) buf := (*bufPtr)[:0] // reset length, keep capacity // ... use buf for scratch work ... buf = append(buf, data...) result := string(buf) // Return to pool â DON'T use buf after this *bufPtr = buf bufPool.Put(bufPtr) return result } // Important constraints: // 1. The GC MAY clear the pool between any two GC cycles // Do NOT rely on objects in the pool surviving across GCs // 2. Objects must be safe to reset to a clean state before reuse // 3. Do NOT store pointers to pool objects â return them before the caller returns // Real-world examples: // - encoding/json uses sync.Pool for encoder/decoder scratch buffers // - fmt uses sync.Pool for pp (print state) objects // - net/http uses sync.Pool for request buffers // Anti-patterns: // - Pooling objects that hold open file descriptors or connections // - Pooling objects that are expensive to validate/clean on reuse // - Using Pool for long-lived objects (GC will evict them)
The GC clears sync.Pool during each collection cycle — pool items are not permanent. This is intentional: the pool exists only to reduce per-GC-cycle allocation pressure, not to replace a cache. If you need objects to survive GC cycles, use a channel-based pool or a properly-designed LRU cache.
More Related questions...