> ## 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.

# Stack

> Generic LIFO stack with multiple backing implementations.

`Stack` is a generic last-in, first-out (LIFO) data structure. The most
recently pushed element is the first to be popped. The library provides four
implementations that share a common interface, each with different allocation
strategies.

## Installation

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

## Interface

```go theme={null}
type Stack[E any] interface {
    Push(E)
    Pop() (e E, ok bool)
}
```

| Method                 | Description                                                                                                  |
| ---------------------- | ------------------------------------------------------------------------------------------------------------ |
| `Push(e E)`            | Places an element on top of the stack.                                                                       |
| `Pop() (e E, ok bool)` | Removes and returns the top element. If the stack is empty, returns the zero value of `E` and `ok == false`. |

## Constructors

All four constructors accept a `sizeHint` parameter and return `container.Stack[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 NewSliceStack theme={null}
  s := stack.NewSliceStack[int](100)
  ```

  ```go NewListStack theme={null}
  s := stack.NewListStack[int](100)
  ```

  ```go NewListSyncPoolStack theme={null}
  s := stack.NewListSyncPoolStack[int](100)
  ```

  ```go NewListInternalPoolStack theme={null}
  s := stack.NewListInternalPoolStack[int](100)
  ```
</CodeGroup>

### Choosing an implementation

| Constructor                | Backing store                     | Notes                                                                                                                              |
| -------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `NewSliceStack`            | Go slice                          | Simplest. Good default choice. `sizeHint` pre-allocates the slice.                                                                 |
| `NewListStack`             | Singly-linked list                | No pre-allocation; each element is a separate heap allocation.                                                                     |
| `NewListSyncPoolStack`     | Linked list + `sync.Pool`         | Pre-heats a `sync.Pool` with `sizeHint` nodes to reduce GC pressure under high throughput.                                         |
| `NewListInternalPoolStack` | 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. Always check for it via a type assertion rather than relying on a
specific implementation.

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

<Note>
  `Len()` is not part of the core `Stack` 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/stack"
)

type Frame int

func main() {
    const sizeHint = 100
    s := stack.NewSliceStack[Frame](sizeHint)

    s.Push(Frame(1))
    s.Push(Frame(2))
    s.Push(Frame(3))

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

    // Drain the stack — LIFO order.
    for {
        e, ok := s.Pop()
        if !ok {
            break
        }
        fmt.Printf("popped: %v\n", e)
    }

    // Pop on an empty stack returns the zero value and ok=false.
    e, ok := s.Pop()
    fmt.Printf("empty pop -> value: %v, ok: %t\n", e, ok)
}
// Output:
// elements in stack: 3
// popped: 3
// popped: 2
// popped: 1
// empty pop -> value: 0, ok: false
```

<Warning>
  `Stack` is not concurrency-safe. Do not share a `Stack` across goroutines
  without external synchronization.
</Warning>
