uuid

A pure Go implementation of RFC-9562 UUIDs, covering generation and parsing for versions 1 and 3 through 8.

Library
Go
vv4.4.0+incompatible
1,811stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
75/100Good
Development Activity72
Maintenance64
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
82/100Excellent
Architecture85
Code Quality92
Innovation62
Learning Curve90

gofrs/uuid provides a dependency-free Go implementation of Universally Unique Identifiers as specified in RFC-9562 (the successor to RFC-4122). It supports the full range of UUID versions still in active use: time-and-MAC-based V1, name-based V3 (MD5) and V5 (SHA-1), random V4, the k-sortable V6 and V7 timestamp-based variants, and the custom-layout V8. The package originated as a fork of satori/go.uuid after that project stalled with known bugs, and the gofrs organization has maintained it as the community’s de facto standard UUID library since.

Beyond generation, the package handles parsing of every common textual UUID form (canonical dashed, braced, URN-prefixed, and bare hex), plus binary and text (un)marshaling, database/sql Valuer/Scanner implementations (including a NullUUID type for nullable columns), and JSON marshaling. A pluggable Generator interface and GenOption functions let callers swap in a custom random source, MAC-address function, or clock, which matters for anyone who needs deterministic or MAC-obfuscated UUIDs in tests or privacy-sensitive contexts.

What You Get

  • Generators for UUID versions 1, 3, 4, 5, 6, 7, and 8, each exposed as both a package-level convenience function and a method on a swappable Generator interface
  • A monotonic, batching-aware V7 generator that guarantees strictly increasing UUIDs from a single generator instance even within the same millisecond or across a backwards clock jump
  • Parsing for canonical, braced, URN-prefixed, and bare-hex textual UUID formats via Parse, FromString, and the encoding.TextUnmarshaler interface
  • First-class database/sql integration through driver.Valuer and sql.Scanner on UUID, plus a NullUUID wrapper type for nullable database columns
  • JSON support via MarshalJSON/UnmarshalJSON on NullUUID and the standard text marshaler on UUID, so UUIDs serialize cleanly in API payloads
  • Configurable generation through GenOption functions (WithRandomReader, WithEpochFunc, WithHWAddrFunc) for deterministic testing or MAC-address obfuscation

Common Use Cases

  • Generating primary keys or external-facing identifiers for database rows using V4 (random) or V7 (time-sortable) UUIDs
  • Producing deterministic, content-derived identifiers with V5 name-based hashing against a fixed namespace
  • Storing and retrieving UUID columns directly as Go values through the database/sql driver interfaces, including nullable columns via NullUUID
  • Building k-sortable identifiers for time-ordered data (event logs, message queues) with V6 or V7, where insertion order should match ID order
  • Parsing and validating UUIDs received from external systems in any of the RFC-9562-accepted text encodings

Under The Hood

Architecture The package is a flat, single-package library split by responsibility across five files rather than layered directories: uuid.go defines the UUID array type, byte layout, and versioned constants; generator.go holds the Gen struct and all NewV* constructors; codec.go handles text/binary parsing and marshaling; sql.go covers database/sql and JSON integration; error.go defines typed sentinel errors. Generation flows through package-level functions like NewV4()/NewV7(), which delegate to a DefaultGenerator built by NewGen(), while callers needing custom randomness, clock, or MAC sources construct their own Gen via NewGenWithOptions — a clean dependency-injection seam that isolates the one genuinely stateful part of the library (the mutex-protected clock sequence and V7 counter in Gen) from the otherwise-pure encode/decode logic elsewhere. The core UUID type has no abstraction layer between it and its byte-level encoding, so every generator and codec function would need to change in lockstep if that layout changed — acceptable rigidity for a value type meant to behave like a fixed-size array.

Tech Stack The module is pure standard library, declaring zero third-party dependencies in go.mod. It draws on crypto/rand for secure randomness in V4/V6/V7 generation, crypto/md5 and crypto/sha1 for V3/V5 name-based hashing, database/sql and database/sql/driver for the Value/Scan integration, encoding/binary for timestamp bit-packing in V1/V6/V7, net for MAC address discovery, and sync (Once, Mutex) to guard one-time initialization and shared counter state. There is no build tooling beyond the standard Go toolchain; CI runs a dedicated Go workflow alongside CodeQL and OpenSSF Scorecard analysis, with Dependabot watching for supply-chain issues.

Code Quality Testing is extensive and table-driven, spanning six test files with dozens of top-level Test functions covering deterministic fixtures for every UUID version, malformed-input parsing cases, and round-trip Scan/Value/MarshalJSON behavior; a pre-commit configuration and multiple CI workflows enforce this on every push. Error handling is explicit and typed throughout, using a custom Error string type that implements the error interface for stable sentinel matching, wrapped with fmt.Errorf’s %w verb so callers can use errors.Is against a shared underlying error. Naming is idiomatic Go, and the code favors named constants over magic numbers, with inline RFC diagrams documenting the trickier bit-packing logic.

What Makes It Unique The library doesn’t invent new UUID semantics — RFC-9562 defines the versions — but its V7 implementation goes beyond the specification’s minimum bar by adding a monotonic counter that guarantees strictly increasing UUIDs from a single generator even when multiple UUIDs are requested within the same millisecond or the system clock moves backwards, a correctness property many other language implementations skip. Its practical edge over generic UUID packages is breadth combined with polish: a single dependency-free package spans every active UUID version, including the rarely-implemented custom V8, with drop-in database/sql and JSON integration baked in.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search