randomizer is a fast, zero-allocation-friendly, and goroutine-safe random data generation library for Go.
It covers numbers, formatted strings, and network addresses — all driven by a lock-free SplitMix64 PRNG seeded from Go's hash/maphash.
- Numbers — random integers (signed & unsigned, any width), and floats in
[0, 1) - Range sampling — unbiased interval generation with Lemire's algorithm (no division in the hot path)
- Strings — decimal, hexadecimal, and octal strings with no adjacent-duplicate characters
- Network — random IPv4, IPv6 (unicast & multicast), and MAC addresses
- Lock-free — the primary PRNG uses an atomic counter; no mutexes on the hot path
- Pool-backed hashing —
maphash.Hashobjects are recycled viasync.Poolfor callers that need them
- Go 1.22 or later (uses
for range Nsyntax andb.Loop()in tests)
go get -u github.com/colduction/randomizer@latestpackage main
import (
"fmt"
"github.com/colduction/randomizer"
)
func main() {
// Random signed integer
fmt.Println(randomizer.Int[int64]())
// Random integer in [1, 100)
fmt.Println(randomizer.IntInterval(int64(1), int64(100)))
// Random float in [0, 1)
fmt.Println(randomizer.Float64())
// Random 16-character hex string (lowercase)
fmt.Println(randomizer.Word.Hex(16, false))
// Random decimal string of length 12
fmt.Println(randomizer.Word.Decimal(12))
// Random IPv4 address
fmt.Println(randomizer.Network.IPv4Addr())
// Random MAC address (locally administered, unicast)
fmt.Println(randomizer.Network.MACAddr(true, false))
}All number functions are zero-allocation and safe to call from multiple goroutines simultaneously.
Returns a random signed integer of the requested type (int8, int16, int, int32, int64).
n8 := randomizer.Int[int8]()
n32 := randomizer.Int[int32]()
n64 := randomizer.Int[int64]()Returns a random unsigned integer (uint8, uint16, uint, uint32, uint64, uintptr).
u := randomizer.Uint[uint64]()Returns a uniformly distributed signed integer in [min, max).
If min == max the value is returned immediately. Swapped bounds are corrected automatically.
// Random number from -50 to 49 (inclusive lower, exclusive upper)
v := randomizer.IntInterval(int64(-50), int64(50))Same as IntInterval but for unsigned types.
// Random number from 1 to 999
v := randomizer.UintInterval(uint64(1), uint64(1000))Returns a random float32 in [0, 1) with 24 bits of precision.
f := randomizer.Float32()Returns a random float64 in [0, 1) with 53 bits of precision.
f := randomizer.Float64()String functions allocate exactly one buffer (the output itself). The String-returning variants avoid a second allocation by aliasing the buffer directly.
All generated strings are guaranteed to have no two adjacent identical characters.
Generates a random decimal string (0–9) of the given length.
s := randomizer.Word.Decimal(12) // e.g. "Morton, 3815"... like "804712639250"Same as Decimal but returns a []byte, avoiding any string conversion.
b := randomizer.Word.DecimalBytes(12)Generates a random hexadecimal string of the given length.
Pass uppercase: true to get A–F; false gives a–f.
lower := randomizer.Word.Hex(32, false) // e.g. "3a9f1b0c..."
upper := randomizer.Word.Hex(32, true) // e.g. "3A9F1B0C..."Same as Hex but returns []byte.
b := randomizer.Word.HexBytes(32, false)Generates a random octal string (0–7) of the given length.
s := randomizer.Word.Octal(8) // e.g. "53107624"Same as Octal but returns []byte.
b := randomizer.Word.OctalBytes(8)All functions return
""/nilforlength <= 0.
Network functions return Go standard-library types (net.IP, net.HardwareAddr) and allocate exactly one slice per call.
Generates a fully random 4-byte IPv4 address.
ip := randomizer.Network.IPv4Addr()
fmt.Println(ip) // e.g. 192.0.2.57Generates a fully random 16-byte IPv6 address.
ip := randomizer.Network.IPv6Addr()
fmt.Println(ip) // e.g. 2001:db8::1Generates a random 6-byte MAC address.
| Parameter | Effect |
|---|---|
local = true |
Sets the U/L bit (locally administered) |
local = false |
Clears the U/L bit (globally unique / OUI enforced) |
multicast = true |
Sets the I/G bit (multicast/broadcast) |
multicast = false |
Clears the I/G bit (unicast) |
// Locally administered unicast (common for virtual/container interfaces)
mac := randomizer.Network.MACAddr(true, false)
fmt.Println(mac) // e.g. 02:1a:3f:7c:d2:88Generates a random IPv6 unicast address with the correct prefix for the requested type.
| Constant | Prefix | Use case |
|---|---|---|
GlobalType |
2000::/3 |
Public internet addresses |
LinkLocalType |
fe80::/10 |
On-link communication only |
SiteLocalType |
fec0::/10 |
Deprecated, site-scoped |
UniqueLocalType / PrivateType |
fd00::/8 |
Private networks (like IPv4 RFC 1918) |
global := randomizer.Network.IPv6UnicastAddr(randomizer.GlobalType)
linkLocal := randomizer.Network.IPv6UnicastAddr(randomizer.LinkLocalType)
private := randomizer.Network.IPv6UnicastAddr(randomizer.PrivateType)Generates a random IPv6 multicast address (ff00::/8) with the given scope nibble.
| Constant | Scope value | Reach |
|---|---|---|
InterfaceLocalScope |
0x1 |
Same interface only |
LinkLocalScope |
0x2 |
Same link/subnet |
AdminLocalScope |
0x4 |
Administratively defined |
SiteLocalScope |
0x5 |
Within a site |
OrgLocalScope |
0x8 |
Within an organisation |
GlobalScope |
0xE |
Internet-wide |
mc := randomizer.Network.IPv6MulticastAddr(randomizer.LinkLocalScope)
fmt.Println(mc) // e.g. ff02::...The hashPool type is the engine behind all randomness in the package. You rarely need to interact with it directly, but it is exported for advanced use cases such as generating raw random bytes or building custom generators.
A package-level *hashPool ready to use. All top-level functions (Int, Float64, Word.*, Network.*) use it internally.
// Raw 64-bit random number
n := randomizer.DefaultHashPool.Sum64()
// Raw 32-bit random number
n32 := randomizer.DefaultHashPool.Sum32()
// Append 8 random bytes to an existing slice
buf := randomizer.DefaultHashPool.Sum(existingSlice)Creates a new independent pool. size must be greater than 0 — pass any positive value to create the pool (the parameter future-proofs capacity hints).
Returns nil for size <= 0, and all methods are safe to call on a nil receiver.
pool := randomizer.NewHashPool(16)
// Borrow a maphash.Hash from the pool
h := pool.Get()
h.WriteString("hello")
fmt.Println(h.Sum64())
pool.Put(h) // always return it when doneBorrow and return a maphash.Hash from the pool. The hash is automatically reset on Put. Always pair every Get with a Put to avoid leaking objects.
h := randomizer.DefaultHashPool.Get()
defer randomizer.DefaultHashPool.Put(h)
h.WriteString("seed-data")
fmt.Printf("%016x\n", h.Sum64())Benchmarks run on an AMD Ryzen 9 7950X, Go 1.26, GOMAXPROCS=32:
| Benchmark | Time/op | Allocs/op |
|---|---|---|
Int[int64] |
~2.8 ns | 0 |
IntInterval (signed) |
~5.9 ns | 0 |
Uint[uint64] |
~2.8 ns | 0 |
UintInterval (unsigned) |
~5.6 ns | 0 |
Float32 |
~2.9 ns | 0 |
Float64 |
~2.9 ns | 0 |
Word.Decimal(256) |
~633 ns | 1 |
Word.Hex(256) |
~411 ns | 1 |
Word.Octal(256) |
~539 ns | 1 |
Network.IPv4Addr |
~11 ns | 1 |
Network.IPv6Addr |
~20 ns | 1 |
Network.MACAddr |
~13 ns | 1 |
All number functions are zero-allocation. String and network functions allocate exactly one buffer — the returned value itself.
Every function in this package is safe to call concurrently from any number of goroutines. The PRNG state is advanced with sync/atomic operations; no mutex is held on the hot path.
This project is licensed under the terms of the MIT License.