Pick the right backing store for your Queue or Stack.
Go Container provides multiple backing-store implementations for Queue and Stack, so you can tune for your workload. For Set and OrderedMap, only one implementation is available, and it is already well-optimized for general use.
The slice-backed implementation is the fastest option in almost every benchmark, particularly when you supply a size hint to preallocate the backing array. Start here unless you have a specific reason to choose otherwise.
Best throughput for both Enqueue/Push and Dequeue/Pop
Preallocating with a size hint eliminates most allocations in the steady state
Consistent top-ranked performance across Go 1.18 and Go 1.24, on both amd64 and arm64
A doubly-linked list that allocates one node per element. Avoids resizing the backing structure when you do not know the capacity in advance, but allocation overhead per operation is significantly higher than a preallocated slice.
No amortized resize penalty when the working set is unbounded
Higher per-operation allocation cost (heap node per element)
A good fallback if you genuinely cannot estimate capacity
A linked list that recycles nodes using an internal pool. This reduces allocation pressure compared to a plain List, and comes close to Slice performance in several benchmarks—but never surpasses it.
Better than plain List; useful when you want to avoid sync.Pool
A linked list that recycles nodes using sync.Pool. In practice this is the slowest option across all benchmarks and architectures.
Avoid ListWithSyncPool unless you have profiled your application and measured a concrete benefit. Benchmark data consistently shows it ranking last in nearly every operation.
Every constructor accepts a sizeHint int argument. When you pass a positive value, the implementation preallocates backing storage for that many elements, avoiding allocations until the collection grows beyond that capacity.
// Preallocate for 128 elements — fastest pathq := queue.NewSliceQueue[MyEvent](128)// No hint — backing storage grows on demandq := queue.NewSliceQueue[MyEvent](0)
Use a size hint whenever you have a reasonable estimate of the working-set size. Even an approximate value improves throughput significantly; it does not need to be exact.
import "github.com/fgm/container/queue"// With size hint (preferred)q := queue.NewSliceQueue[string](64)// Without size hintq := queue.NewSliceQueue[string](0)
import "github.com/fgm/container/stack"// With size hint (preferred)s := stack.NewSliceStack[int](64)// Without size hints := stack.NewSliceStack[int](0)
Only the slice-backed implementation is available. Pass stable: true for in-place updates (highest throughput), or stable: false for recency-based ordering (LRU-style).
When in doubt, reach for NewSliceQueue or NewSliceStack with a size hint. This is the recommended default for most workloads and consistently outperforms all other options in benchmarks.