go-ordered-map
A generic Go library for maps that preserve key insertion order, with constant-time operations and built-in JSON/YAML support.
Repository Health
Technical Analysis
go-ordered-map provides a generic OrderedMap type for Go that behaves like a standard map but remembers the order in which keys were inserted, similar to Python’s collections.OrderedDict. All core operations — Get, Set, Delete, and iteration — run in constant time, backed by a doubly-linked list paired with a standard map for O(1) lookups.
The library supports bidirectional iteration from either the oldest or newest key without extra memory copies, native Go 1.23 range-over-func iterators, and drop-in JSON and YAML marshalling/unmarshalling that preserves key order through custom Marshaler/Unmarshaler implementations.
What You Get
- A generic OrderedMap[K, V] type usable with any comparable key and any value type
- Constant-time Get, Set, Delete, and Move operations backed by a map plus a doubly-linked list
- Bidirectional iteration via Oldest()/Newest() pair traversal or native Go 1.23 iter.Seq/iter.Seq2 iterators
- Built-in JSON and YAML marshalling/unmarshalling that preserves key order
- Capacity hints and initial-data options via WithCapacity and WithInitialData
Common Use Cases
- Preserving JSON object key order when re-serializing config or API payloads
- Implementing LRU-style caches that need O(1) move-to-front/move-to-back semantics
- Building deterministic serialization output for reproducible builds or diffable configs
- Maintaining ordered YAML documents such as CI pipeline definitions
Under The Hood
Architecture
The package is a single flat Go module (orderedmap) built around one core type, OrderedMap[K, V], defined in orderedmap.go: a map[K]*Pair[K, V] for O(1) lookups paired with a doubly-linked list from bahlo/generic-list-go that tracks insertion order, so every pair carries both a map entry and a list element. json.go and yaml.go each add marshalling behavior as separate files that implement the standard library’s Marshaler/Unmarshaler interfaces by walking the same linked list from Oldest() to Newest(), so the core data structure has no knowledge of serialization concerns — a clean, if minimal, separation for a package this size. There are no internal layers or abstractions beyond this because the problem domain doesn’t call for them; changing the underlying list implementation would only touch orderedmap.go.
Tech Stack
Written in Go, requiring Go >= 1.23 to use generics and the iter.Seq/iter.Seq2 range-over-func iterators introduced in that release (an older v2.1.8 tag exists for Go < 1.23, and a v1 branch for pre-generics Go < 1.18). Dependencies are narrowly scoped to the job: bahlo/generic-list-go for the generic doubly-linked list, buger/jsonparser and mailru/easyjson’s jwriter for low-allocation JSON encode/decode, and gopkg.in/yaml.v3 for YAML support. Tests depend on stretchr/testify. There’s no build/deploy tooling beyond a Makefile and CircleCI configuration — this is a library, not a service.
Code Quality
Test coverage is extensive relative to the implementation size: orderedmap_test.go, json_test.go, and yaml_test.go together with dedicated json_fuzz_test.go and yaml_fuzz_test.go files (using Go’s native fuzzing support) total over 1,500 lines against roughly 600 lines of implementation. .golangci.yml enables a wide set of linters (errcheck, errorlint, gocognit, goconst, dupl, funlen, and more) with disable-all: true as the baseline, meaning only explicitly chosen checks run — a deliberate, curated lint policy rather than defaults. CircleCI runs the suite on every push. Error handling is explicit and typed via a dedicated KeyNotFoundError[K] rather than sentinel errors or panics for expected failure paths.
API Design
The public API deliberately mirrors familiar Go idioms: Load/Store are provided as aliases for Get/Set to match sync.Map’s naming, and iteration follows the container/list pattern of Oldest()/Next() and Newest()/Prev(). Construction uses a small functional-options pattern (WithCapacity, WithInitialData, WithDisableHTMLEscape) layered on a single New[K, V](options ...any) constructor, so getting started requires only one import and one call. Every exported type and method carries a godoc comment, and the README documents each feature with a runnable example plus an explicit comparison against four alternative ordered-map implementations, naming the specific tradeoff (linear deletes, goroutine-leaking channel iteration) each one avoids.
Used by 3 apps in this directory
ezBookkeeping
Invoicing Finance
Lightweight self-hosted personal finance manager with AI receipt scanning, multi-currency support, and MCP integration for complete data privacy.
Ollama
AI Development · Developer Tools
Run Llama, Gemma, DeepSeek, and other open LLMs on your own machine with one command and an OpenAI-compatible API.
Uptrace
Monitoring · Devops
Unified open-source APM that collects OpenTelemetry traces, metrics, and logs into a single self-hosted platform backed by ClickHouse.