Sync Pool Non Pointer
ID |
go.sync_pool_non_pointer |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Efficiency |
Language |
Go |
Tags |
efficiency, suspicious |
Description
Reports a sync.Pool composite literal whose New function returns a non-pointer value (a struct
or other value type) instead of a pointer. Storing a value type in the pool’s interface{} slots
boxes it on every Put and copies it out on every Get, which defeats the purpose of pooling.
Rationale
A sync.Pool exists to reuse allocations. When New returns a value type, putting it into the
pool’s interface{} storage allocates on the heap to box it, and getting it back copies it out, so
the allocations the pool was meant to avoid happen on every use. Returning a pointer (&T{}) keeps
a single heap object that is genuinely reused. The check is conservative: it flags only a
sync.Pool literal whose New returns a composite literal not taken by address, or a basic
literal.
sync.Pool{New: func() interface{} { return Buffer{} }} // FLAW — value boxed on every use
sync.Pool{New: func() interface{} { return &Buffer{} }} // OK — returns a pointer
Remediation
Return a pointer from New (return &T{}) so the pool stores and reuses a single heap object.