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

# Quick Start

> Install Go Container and use your first data structure in minutes.

This guide walks you through installing Go Container and using three of its data structures: `Queue`, `Stack`, and `Set`.

## Prerequisites

* Go 1.18 or later (generics support is required).
* A Go module initialized with `go mod init`.

## Steps

<Steps>
  <Step title="Install the module">
    Add `github.com/fgm/container` to your module:

    ```bash theme={null}
    go get github.com/fgm/container
    ```
  </Step>

  <Step title="Use a Queue">
    Import the `queue` sub-package and create a slice-backed queue with a size hint.

    ```go theme={null}
    package main

    import (
        "fmt"

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

    type Element int

    // sizeHint is an indication of the maximum number of elements expected.
    // It is not a hard limit — implementations may use it to pre-allocate storage.
    const sizeHint = 100

    func main() {
        var e Element = 42

        q := queue.NewSliceQueue[Element](sizeHint)
        q.Enqueue(e)

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

        // Dequeue returns the element and a boolean indicating success.
        for i := 0; i < 2; i++ {
            e, ok := q.Dequeue()
            fmt.Printf("Element: %v, ok: %t\n", e, ok)
        }
    }
    ```

    **Output:**

    ```
    elements in queue: 1
    Element: 42, ok: true
    Element: 0, ok: false
    ```

    <Tip>
      The second `Dequeue` returns the zero value and `ok: false` because the queue is empty. Always check `ok` before using the returned element.
    </Tip>
  </Step>

  <Step title="Use a Stack">
    Import the `stack` sub-package. The API mirrors the queue — `Push` and `Pop` instead of `Enqueue` and `Dequeue`.

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

    s := stack.NewSliceStack[Element](sizeHint)
    s.Push(e)

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

    for i := 0; i < 2; i++ {
        e, ok := s.Pop()
        fmt.Printf("Element: %v, ok: %t\n", e, ok)
    }
    ```

    **Output:**

    ```
    elements in stack: 1
    Element: 42, ok: true
    Element: 0, ok: false
    ```
  </Step>

  <Step title="Use a Set">
    Import the `set` sub-package. `Set` eliminates duplicates and supports standard set operations.

    ```go theme={null}
    import (
        "fmt"

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

    func main() {
        var e Element = 42

        s := set.NewBasicMap[Element](sizeHint)

        // Add the squares of 0..41 to the set.
        for i := range e {
            s.Add(i * i)
        }

        if cs, ok := s.(container.Countable); ok {
            fmt.Printf("elements in set: %d\n", cs.Len())
        }

        // Remove elements — Remove is safe to call even for absent items.
        for i := Element(0); i < 10; i++ {
            del := i * i * i
            ok := s.Remove(del)
            fmt.Printf("Element: %3v ok: %t\n", del, ok)
        }
    }
    ```
  </Step>

  <Step title="Use a WaitableQueue for concurrent code">
    `WaitableQueue` is the only concurrency-safe type in the module. It uses a `WaitChan` to signal consumers when items are available, avoiding the capacity constraints of Go channels.

    ```go theme={null}
    package main

    import (
        "fmt"
        "time"

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

    type Element int

    func consumer(wq container.WaitableQueue[Element]) {
        lq := wq.(container.Countable)

        for {
            _, ok := <-wq.WaitChan()
            if !ok {
                fmt.Printf("Consumer exiting, %d remaining\n", lq.Len())
                return
            }
            for {
                item, ok, _ := wq.Dequeue()
                if !ok {
                    break
                }
                fmt.Printf("Received: %v, %d in queue\n", item, lq.Len())
            }
        }
    }

    func main() {
        const sizeHint, low, high = 200, 50, 150

        wq, err := queue.NewWaitableQueue[Element](sizeHint, low, high)
        if err != nil {
            panic(err)
        }

        go consumer(wq)

        for i := range 10 {
            wq.Enqueue(Element(i))
            time.Sleep(2 * time.Millisecond)
        }

        wq.Close() // Unblocks consumers waiting on WaitChan.
        time.Sleep(50 * time.Millisecond)
    }
    ```

    <Note>
      Call `Close()` on the queue when the producer is done. This unblocks any consumers that are waiting on `WaitChan`, allowing them to drain remaining items and exit cleanly.
    </Note>
  </Step>
</Steps>

## The size hint pattern

Every constructor accepts a `sizeHint` argument. This is a hint — not a hard cap — that slice-backed implementations use to pre-allocate storage and avoid repeated resizing:

```go theme={null}
const sizeHint = 100

q := queue.NewSliceQueue[MyType](sizeHint)
s := stack.NewSliceStack[MyType](sizeHint)
om := orderedmap.NewSlice[string, int](sizeHint, true)
```

Pass `0` if you have no estimate. The implementation will still work correctly, just without the pre-allocation benefit.

## Import paths

| Data structure  | Import path                           | Constructor example                              |
| --------------- | ------------------------------------- | ------------------------------------------------ |
| `OrderedMap`    | `github.com/fgm/container/orderedmap` | `orderedmap.NewSlice[K, V](sizeHint, stable)`    |
| `Queue`         | `github.com/fgm/container/queue`      | `queue.NewSliceQueue[E](sizeHint)`               |
| `WaitableQueue` | `github.com/fgm/container/queue`      | `queue.NewWaitableQueue[E](sizeHint, low, high)` |
| `Set`           | `github.com/fgm/container/set`        | `set.NewBasicMap[E](sizeHint)`                   |
| `Stack`         | `github.com/fgm/container/stack`      | `stack.NewSliceStack[E](sizeHint)`               |

<Warning>
  All implementations except `WaitableQueue` are **not safe for concurrent use**. Protect them with a `sync.Mutex` or equivalent when sharing across goroutines.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="OrderedMap" icon="map" href="/data-structures/ordered-map">
    Explore stable and recency ordering modes.
  </Card>

  <Card title="WaitableQueue" icon="layer-group" href="/data-structures/waitable-queue">
    Learn about watermarks and flow control for concurrent queues.
  </Card>

  <Card title="Set operations" icon="circle-nodes" href="/data-structures/set">
    Use Union, Intersection, and Difference on your sets.
  </Card>

  <Card title="Choosing an implementation" icon="code-compare" href="/guides/choosing-implementation">
    Pick the right backing store for your performance profile.
  </Card>
</CardGroup>
