container

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 17, 2025 License: Apache-2.0 Imports: 2 Imported by: 0

README

Go containers

GoDoc Go Report Card github codecov OpenSSF Scorecard OpenSSF Best Practices

This module contains minimal type-safe Ordered Map, Queue, Set and Stack implementations using Go generics.

The Ordered Map supports both stable (in-place) updates and recency-based ordering, making it suitable both for highest performance (in-place), and for LRU caches (recency).

Contents

See the available types by underlying storage

Type Slice Map List List+sync.Pool List+int. pool Recommended
OrderedMap Y Slice with size hint
Queue Y Y Y Y Slice with size hint
WaitableQueue Y Slice with size hint
Set Y Map with size hint
Stack Y Y Y Y Slice with size hint

CAVEAT: In order to optimize performance, except for WaitableQueue, all of these implementations are unsafe for concurrent execution, so they need protection in concurrency situations.

WaitableQueue being designed for concurrent code, on the other hand, is concurrency-safe.

Generally speaking, in terms of performance:

  • Slice > list+internal pool > plain List > list+sync.Pool
  • Preallocated > not preallocated

See BENCHARKS.md for details.

Usage

See complete listings in:

Ordered Map
stable := true
om := orderedmap.NewSlice[Key, Value](sizeHint, stable) // OrderedMap and Countable
om.Store(k, v)
om.Range(func (k K, v V) bool { fmt.Println(k, v); return true })
v, loaded := om.Load(k)
if !loaded {
        fmt.Fprintf(w, "No entry for key %v\n", k)
}
om.Delete(k) // Idempotent: does not fail on nonexistent keys.
Classic Queues without flow control
var e Element
q := queue.NewSliceQueue[Element](sizeHint)
q.Enqueue(e)
if lq, ok := q.(container.Countable); ok {
        fmt.Fprintf(w, "elements in queue: %d\n", lq.Len())
}
for i := 0; i < 2; i++ {
        e, ok := q.Dequeue()
        fmt.Fprintf(w, "Element: %v, ok: %t\n", e, ok)
}
WaitableQueue: a concurrent queue with flow control
var e Element
q, _ := queue.NewWaitableQueue[Element](sizeHint, lowWatermark, highWatermark)
go func() {
        wqs := q.Enqueue(e)
        if lq, ok := q.(container.Countable); ok {
                fmt.Fprintf(w, "elements in queue: %d, status: %s\n", lq.Len(), wqs)
        }
}
<-q.WaitChan()                    // Wait for elements to be available to dequeue
for i := 0; i < 2; i++ {          // Then dequeue them
        e, ok, wqs := q.Dequeue() // Non-blocking, ok will be true for the first and false for the second 
        fmt.Fprintf(w, "Element: %v, ok: %t, status: %s\n", e, ok, wqs)
}
q.Close() // Only needed if consumers may still be waiting on <-q.WaitChan
Sets
var e Element
s := set.NewBasicMap[Element](sizeHint)
s.Add(e)
s.Add(e)
if cs, ok := q.(container.Countable); ok {
        fmt.Fprintf(w, "elements in set: %d\n", cs.Len()) // 1
}
for e := range s.Items() {
        fmt.Fprintln(w, e)
}

Stacks
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)
}
Running tests
Normal tests: unit and benchmarks

The complete test coverage requires running not only the unit tests, but also the benchmarks, like:

    go test -race -run=. -bench=. -coverprofile=cover.out -covermode=atomic ./...

This will also run the fuzz tests in unit test mode, without triggering the fuzzing logic.

Fuzz tests

Fuzz tests are not run by CI, but you can run them on-demand during development with:

    go test -run='^$' -fuzz='^\QFuzzBasicMapAdd\E$'   -fuzztime=20s ./set
    go test -run='^$' -fuzz='^\QFuzzBasicMapItems\E$' -fuzztime=20s ./set
    go test -run='^$' -fuzz='^\QFuzzBasicMapUnion\E$' -fuzztime=20s ./set
  • Adjust -fuzztime duration as relevant: 20 seconds is just a smoke test.
  • Be sure to escape the ^$ and \Q\E characters in the -fuzz argument in your shell.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Countable

type Countable interface {
	Len() int
}

Countable MAY be provided by some implementations. For concurrency-safe types, it is not atomic vs other operations, meaning it MUST NOT be used to take decisions, but only as an observability/debugging tool.

type OrderedMap

type OrderedMap[K comparable, V any] interface {
	Delete(key K)
	Load(key K) (value V, loaded bool)
	// Range is similar to the sync.Map Range method but can fail if the callback deletes map entries.
	Range(func(key K, value V) bool)
	Store(key K, value V)
}

OrderedMap has the same API as a sync.Map for the specific case of OrderedMap[any, any].

type Queue

type Queue[E any] interface {
	Enqueue(E)
	// Dequeue removes the first element from the queue. If the queue is empty,
	// it returns the zero value of the element type, and ok is false.
	Dequeue() (e E, ok bool)
}

Queue is a generic queue with no concurrency guarantees. Instantiate by queue.New<implementation>Queue(sizeHint). The size hint MAY be used by some implementations to optimize storage.

type Set added in v0.2.0

type Set[E comparable] interface {
	Add(item E) (found bool)
	Remove(item E) (found bool)
	Contains(item E) bool
	Clear() (count int)
	Items() iter.Seq[E]

	Union(other Set[E]) Set[E]
	Intersection(other Set[E]) Set[E]
	Difference(other Set[E]) Set[E]
}

type Stack

type Stack[E any] interface {
	Push(E)
	// Pop removes the top element from the stack. If the stack is empty,
	// it returns the zero value of the element type, and ok is false.
	Pop() (e E, ok bool)
}

Stack is a generic queue with no concurrency guarantees. Instantiate by stack.New<implementation>Stack(sizeHint). The size hint MAY be used by some implementations to optimize storage.

type Unit added in v0.2.0

type Unit = struct{}

Unit is a zero-sized struct used as a placeholder in some generic types.

type WaitableQueue added in v0.2.0

type WaitableQueue[E any] interface {
	// Close the queue, preventing any further enqueueing, and unblocking all consumers waiting on WaitChan.
	// In most cases, it only makes sense to have it closed by the producer.
	Close()
	// Dequeue removes the first element from the queue if any is present.
	// If the queue is empty, it returns the zero value of the element type, ok is false, and the result is QueueIsBelowLowWatermark.
	// QueueIsAboveHighWatermark should be used to scale the consumer up or trigger a producer throttle.
	// QueueIsNearSaturation is the same, just more urgent, and is more useful on the Enqueue method.
	Dequeue() (e E, ok bool, result WaitableQueueState)
	// Enqueue adds an element to the queue.
	// Most applications will ignore the result of this call:
	// the most common reason to use it is checking for QueueIsNearSaturation as a trigger for producer throttling.
	// Beware of using QueueIsBelowLowWatermark as a sign to resume production,
	// as you will never get it if you do not call the method,
	// meaning your producer could never unthrottle if it completely stops emitting.
	// In most cases, use the Dequeue / WaitChan side for flow control instead.
	Enqueue(E) WaitableQueueState
	// WaitChan returns a channel that signals when an item might be available to dequeue or when the queue is closed.
	WaitChan() <-chan Unit
}

WaitableQueue is a concurrency-safe generic unbounded queue. It is meant to be used in a producer-consumer pattern, where the blocking behavior and capacity limits of channels are an issue.

type WaitableQueueState added in v0.2.0

type WaitableQueueState int
const (
	QueueIsEmpty              WaitableQueueState = iota // Only set at creation, not in regular use
	QueueIsBelowLowWatermark                            // Below low watermark
	QueueIsNominal                                      // Between low and high watermarks
	QueueIsAboveHighWatermark                           // Above high watermark
	QueueIsNearSaturation                               // Queue almost at full capacity: this is an emergency signal which may be used to trigger load shedding.
)

func (WaitableQueueState) String added in v0.2.0

func (i WaitableQueueState) String() string

Directories

Path Synopsis
cmd
orderedmap command
queuestack command
set command
waitablequeue command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL