> ## Documentation Index
> Fetch the complete documentation index at: https://osinet.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Queue

> Generic FIFO queue with multiple backing implementations.

`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

```go theme={null}
import "github.com/fgm/container/queue"
```

## Interface

```go theme={null}
type Queue[E any] interface {
    Enqueue(E)
    Dequeue() (e E, ok bool)
}
```

| Method                     | Description                                                                                                    |
| -------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `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]`.

<ParamField path="sizeHint" type="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.
</ParamField>

<CodeGroup>
  ```go NewSliceQueue theme={null}
  q := queue.NewSliceQueue[int](100)
  ```

  ```go NewListQueue theme={null}
  q := queue.NewListQueue[int](100)
  ```

  ```go NewListSyncPoolQueue theme={null}
  q := queue.NewListSyncPoolQueue[int](100)
  ```

  ```go NewListInternalPoolQueue theme={null}
  q := queue.NewListInternalPoolQueue[int](100)
  ```
</CodeGroup>

### Choosing an implementation

| Constructor                | Backing store                     | Notes                                                                                                                              |
| -------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `NewSliceQueue`            | Go slice                          | Simplest. Good default choice. `sizeHint` pre-allocates the slice.                                                                 |
| `NewListQueue`             | Singly-linked list                | No pre-allocation; each element is a separate heap allocation.                                                                     |
| `NewListSyncPoolQueue`     | Linked list + `sync.Pool`         | Pre-heats a `sync.Pool` with `sizeHint` nodes to reduce GC pressure under high throughput.                                         |
| `NewListInternalPoolQueue` | Linked list + internal slice pool | Keeps 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.

```go theme={null}
if c, ok := q.(container.Countable); ok {
    fmt.Printf("elements in queue: %d\n", c.Len())
}
```

<Note>
  `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.
</Note>

## Example

```go theme={null}
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
```

<Warning>
  `Queue` is not concurrency-safe. Do not share a `Queue` across goroutines
  without external synchronization. For concurrent producer-consumer scenarios,
  use [`WaitableQueue`](/data-structures/waitable-queue) instead.
</Warning>
