Skip to main content
Queue is a generic first-in, first-out (FIFO) data structure. Elements are removed in the same order they were inserted. The library provides four implementations that share a common interface, each with different allocation strategies so you can choose the best fit for your workload.

Installation

import "github.com/fgm/container/queue"

Interface

type Queue[E any] interface {
    Enqueue(E)
    Dequeue() (e E, ok bool)
}
MethodDescription
Enqueue(e E)Appends an element to the back of the queue.
Dequeue() (e E, ok bool)Removes and returns the front element. If the queue is empty, returns the zero value of E and ok == false.

Constructors

All four constructors accept a sizeHint parameter and return container.Queue[E].
sizeHint
int
required
A non-binding hint for the initial capacity. Some implementations use it to pre-allocate storage; others ignore it. Pass 0 if you have no estimate.
q := queue.NewSliceQueue[int](100)

Choosing an implementation

ConstructorBacking storeNotes
NewSliceQueueGo sliceSimplest. Good default choice. sizeHint pre-allocates the slice.
NewListQueueSingly-linked listNo pre-allocation; each element is a separate heap allocation.
NewListSyncPoolQueueLinked list + sync.PoolPre-heats a sync.Pool with sizeHint nodes to reduce GC pressure under high throughput.
NewListInternalPoolQueueLinked list + internal slice poolKeeps a bounded pool of recycled nodes inside the struct — no sync.Pool overhead. Best when allocation patterns are predictable.

Optional Countable interface

Some implementations also satisfy container.Countable, which adds a Len() method. You should always check for it at runtime via a type assertion rather than relying on a specific implementation.
if c, ok := q.(container.Countable); ok {
    fmt.Printf("elements in queue: %d\n", c.Len())
}
Len() is not part of the core Queue interface because not all implementations provide it. Always guard the call with a type assertion as shown above.

Example

package main

import (
    "fmt"

    "github.com/fgm/container"
    "github.com/fgm/container/queue"
)

type Task int

func main() {
    const sizeHint = 100
    q := queue.NewSliceQueue[Task](sizeHint)

    q.Enqueue(Task(1))
    q.Enqueue(Task(2))
    q.Enqueue(Task(3))

    // Optionally check the length if the implementation supports it.
    if c, ok := q.(container.Countable); ok {
        fmt.Printf("elements in queue: %d\n", c.Len())
    }

    // Drain the queue.
    for {
        e, ok := q.Dequeue()
        if !ok {
            break
        }
        fmt.Printf("dequeued: %v\n", e)
    }

    // Dequeue on an empty queue returns the zero value and ok=false.
    e, ok := q.Dequeue()
    fmt.Printf("empty dequeue -> value: %v, ok: %t\n", e, ok)
}
// Output:
// elements in queue: 3
// dequeued: 1
// dequeued: 2
// dequeued: 3
// empty dequeue -> value: 0, ok: false
Queue is not concurrency-safe. Do not share a Queue across goroutines without external synchronization. For concurrent producer-consumer scenarios, use WaitableQueue instead.