fastrand

package module
v0.0.0-...-a0baaf2 Latest Latest
Warning

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

Go to latest
Published: Feb 5, 2026 License: MIT Imports: 18 Imported by: 0

README

FastRand for Go

Go Report Card GoDoc

FastRand is a high-performance, zero-dependency Go library for generating random data. It provides a comprehensive suite of tools, from simple numbers to complex templated strings, with both cryptographic (ChaCha8) and non-cryptographic (PCG) sources. It is engineered to be a faster, more powerful, and more ergonomic replacement for Go's standard math/rand and crypto/rand packages for common tasks.


Table of Contents

  1. Why FastRand? The Performance Advantage
  2. Core Features
  3. Performance Snapshot
  4. Installation
  5. Core Concepts: Package vs. Engine
  6. Complete API Reference
  7. The Randomizer Engine: In-Depth
  8. The Configurable Engine: Full Customization
  9. Concurrency
  10. Project Information
  11. License

Why FastRand? The Performance Advantage

FastRand is not just another random library; it's an intentional upgrade designed to address the performance and ergonomic limitations of Go's standard libraries for common, high-throughput use cases.

1. Superior PRNG Algorithm (vs. math/rand)

The default non-secure generator in FastRand is built on Go 1.22+'s math/rand/v2 with a PCG (Permuted Congruential Generator) source.

  • Speed: PCG is significantly faster than the legacy math/rand source. This allows for primitive generation (ints, floats) in 1-2 nanoseconds.
  • Statistical Quality: PCG offers better statistical properties, passing modern test suites where the old default generator would fail.
  • Memory Efficiency: Core functions are engineered to be zero-allocation, meaning they can be called millions of times without creating any work for Go's garbage collector. This is critical for maintaining low latency in hot paths.

Result: A generator that is faster, statistically better, and more memory-efficient than the standard library's math/rand.

2. High-Performance CSPRNG (vs. crypto/rand)

The secure generator is built on ChaCha8, a modern, high-speed stream cipher widely used in protocols like TLS 1.3.

  • In-Process Speed: crypto/rand is a thin wrapper around OS-level entropy sources (e.g., /dev/urandom). While secure, this can involve system calls and potential lock contention under high concurrency. ChaCha8 runs entirely within your Go process, making it an extremely fast and reliable source for cryptographic needs.
  • Ergonomic API: FastRand provides a rich, developer-friendly API (SecureIntN, SecureString, SecureNumber) that is much more convenient than manually reading from crypto.Reader and performing biasing calculations.

Result: You get the security guarantees needed for cryptographic tasks with a significant performance boost and a much better developer experience.

3. Extreme Memory Optimization

The Randomizer engine is the library's most powerful feature, but it's also a performance showcase.

  • Buffer Pooling: Instead of creating and discarding bytes.Buffer objects on every call, the engine uses a bytebufferpool to recycle memory. This dramatically reduces GC pressure in applications that generate many templated strings.
  • Allocation-Free Parsing: The engine's internal parser is handwritten to avoid Go's standard strings.Split function, which allocates new slices. By manually scanning for delimiters, the engine processes templates with almost no memory overhead.

Result: A templating engine that is not only powerful but also incredibly efficient, making it suitable for performance-critical tasks like generating mock logs, API responses, or test data at scale.

Core Features

  • Dual Random Sources: Blazing-fast PCG for general use and secure ChaCha8 for cryptographic needs.
  • Configurable Randomizer Engine: Create isolated engine instances with custom rules, keywords, character sets, and length constraints.
  • Simple & Idiomatic API: Intuitive functions like IntN, String, and Bytes.
  • Type-Safe Generics: Generate random numbers for any standard integer or float type with Number[T]().
  • Rich Helper Functions: One-line functions for IPv4, IPv6, UUID, Hex, and more.
  • Powerful Slice & Map Tools: Choice an element, select ChoiceMultiple elements, Shuffle a slice, or pick a ChoiceKey from a map.
  • Concurrency Safe: All functions are safe for concurrent use in goroutines.
  • Zero Dependencies: Relies only on the Go standard library and the optional, high-performance bytebufferpool.

Performance Snapshot

Benchmarks highlight the significant performance gains over standard practices.

Benchmark Speed (ns/op) Memory (B/op) Allocations (allocs/op)
fastrand.IntN ~2.4 ns/op 0 B/op 0 allocs/op
fastrand.SecureBytes(64) ~42 ns/op 64 B/op 1 alloc/op
crypto/rand.Read(64) ~76 ns/op 0 B/op 0 allocs/op
fastrand.Randomizer ~1245 ns/op ~693 B/op ~13 allocs/op

The Randomizer's result of ~13 allocations for parsing a complex template with 5 different placeholders is exceptionally low and demonstrates the effectiveness of the memory optimizations.

Installation

go get github.com/IzomSoftware/fastrand

Core Concepts: Package vs. Engine

FastRand offers two modes of operation:

  1. Package-Level Functions: For quick and common tasks, you can use functions directly from the package (e.g., fastrand.IntN(10)). These all use a pre-configured, shared "default engine" that is optimized for general use.

  2. The Configurable Engine: For advanced control, you can create your own Engine instance (fastrand.NewEngine(...)). This gives you an isolated, reusable generator with its own unique set of rules, custom keywords, and output formats. This is the recommended approach for building complex, testable systems.

Complete API Reference

Numeric Generation
Int(min, max int) int

Generates a random integer within the inclusive range [min, max]. Panics if min > max.

num := fastrand.Int(-50, 50) // e.g., -23

Note: Uses the fast PCG source.

IntN(n int) int

Generates a random integer within the half-open range [0, n). Panics if n <= 0.

index := fastrand.IntN(100) // e.g., 76

Note: Uses the fast PCG source. Zero-allocation.

Float64() float64

Generates a random float64 in the half-open range [0.0, 1.0).

f := fastrand.Float64() // e.g., 0.12345

Note: Uses the fast PCG source. Zero-allocation.

Bool() bool

Returns true or false with equal probability.

isEnabled := fastrand.Bool() // e.g., true
Number[T number](min, max T) T

A generic function to generate a random number of any standard integer or float type T within the inclusive range [min, max].

var num_i16 int16 = fastrand.Number[int16](-1000, 1000)
var num_u32 uint32 = fastrand.Number[uint32](0, 50000)
var num_f32 float32 = fastrand.Number[float32](-10.5, 10.5)
NumberN[T number](n T) T

A generic function to generate a random number of type T within the inclusive range [0, n].

val := fastrand.NumberN[int64](10000)
String & Byte Generation
Bytes(length int) []byte

Generates a slice of length random bytes.

data := fastrand.Bytes(16)

Note: Uses the fast PCG source. Performs one allocation for the slice.

Hex(length int) string

Generates length random bytes and returns them as a 2x-length hexadecimal string.

token := fastrand.Hex(8) // e.g., "a1b2c3d4e5f6a7b8" (16 chars)
String(length int, charset CharsList) string

Generates a random string of a given length using characters from the provided charset.

// Pre-defined charsets:
// CharsDigits, CharsAlphabetLower, CharsAlphabetUpper, CharsAlphabet,
// CharsAlphabetDigits, CharsSymbolChars, CharsAll

pin := fastrand.String(8, fastrand.CharsDigits) // e.g., "91827364"
id := fastrand.String(12, fastrand.CharsAlphabetUpper) // e.g., "QWERTYASDFZX"
Slice & Map Utilities
Choice[T any](items []T) T

Selects and returns one random element from a slice. Panics if the slice is empty.

names := []string{"Alice", "Bob", "Charlie"}
winner := fastrand.Choice(names) // e.g., "Bob"
ChoiceKey[T comparable, V any](items map[T]V) T

Selects and returns one random key from a map. Panics if the map is empty.

scores := map[string]int{"alpha": 100, "beta": 200}
team := fastrand.ChoiceKey(scores) // e.g., "beta"
ChoiceMultiple[T any](items []T, count int) []T

Selects count unique random elements from a slice and returns them in a new slice.

users := []string{"A", "B", "C", "D", "E"}
winners := fastrand.ChoiceMultiple(users, 3) // e.g., ["D", "A", "C"]

Note: Uses an efficient partial shuffle algorithm.

Shuffle(n int, swap func(i, j int))

Shuffles a collection of n elements in place using the provided swap function.

numbers := []int{1, 2, 3, 4, 5}
fastrand.Shuffle(len(numbers), func(i, j int) {
	numbers[i], numbers[j] = numbers[j], numbers[i]
})
// numbers is now shuffled, e.g., [3, 1, 5, 2, 4]
Perm(n int) []int

Returns a random permutation of the integers [0, n).

indices := fastrand.Perm(5) // e.g., [4, 1, 0, 3, 2]
Network & ID Generation
IPv4() net.IP

Generates a random net.IP representing a v4 address.

ip := fastrand.IPv4() // e.g., 198.51.100.10
IPv6() net.IP

Generates a random net.IP representing a v6 address.

ip := fastrand.IPv6() // e.g., 2001:db8::1234:5678
MustFastUUID() []byte

Generates a fast, non-secure v4 UUID as a 16-byte slice. Panics on error.

uuid := fastrand.MustFastUUID()
Cryptographically Secure Functions

These functions use the ChaCha8 source and are suitable for generating passwords, keys, tokens, and other sensitive data. All Secure* functions that can fail return an error.

  • SecureInt(min, max int) (int, error): Secure integer in [min, max].
  • SecureBytes(length int) ([]byte, error): Secure byte slice.
  • SecureHex(length int) (string, error): Secure hex string.
  • SecureString(length int, charset CharsList) (string, error): Secure string from a charset.
  • SecureIPv4() (net.IP, error): Secure IPv4 address.
  • SecureIPv6() (net.IP, error): Secure IPv6 address.
  • SecureFloat64() float64: Secure float in [0.0, 1.0).
  • SecureNumber[T number](min, max T) (T, error): Secure generic number.
  • MustSecureUUID() []byte: Secure v4 UUID. Panics on error.
// Example: Generate a 32-character secure password
password, err := fastrand.SecureString(32, fastrand.CharsAll)
if err != nil {
    panic(err)
}
fmt.Println("Secure Password:", password)

The Randomizer Engine: In-Depth

The Randomizer is the library's most powerful feature, allowing you to generate complex, structured data from a single template string.

Placeholder Syntax

The engine parses a string and replaces placeholders with random data. The syntax is flexible and powerful:

{RAND[OM];[LENGTH];[TYPE]}

  • OM: The OM is optional. {RAND...} and {RANDOM...} are equivalent.
  • [LENGTH]: An optional parameter that can be:
    • A single integer: {RAND;10;...}
    • A comma-separated list of choices: {RAND;5,10,15;...}
    • A hyphen-separated range: {RAND;5-10;...}
  • [TYPE]: An optional keyword specifying the data type. Can be a single keyword or a comma-separated list of choices.
Built-in Keywords
Keyword Description Example Output (for length 8)
ABL Alphabet, Lowercase abcdefgh
ABU Alphabet, Uppercase ABCDEFGH
ABR Alphabet, Random Case AbCdEfGh
DIGIT Digits (0-9) 12345678
HEX Hexadecimal (0-f) a1b2c3d4e5f6a7b8 (16 chars)
UUID A v4 UUID (length ignored) xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
IPV4 An IPv4 address (length ignored) 192.0.2.1
IPV6 An IPv6 address (length ignored) 2001:db8::...
EMAIL A random email address abcdefgh@gmail.com
BYTES Raw bytes (length respected) [...8 bytes...]
SPACE Whitespace characters
NULL Null bytes (\x00 - \x0F) [...8 null bytes...]
(default) CharsAll if no keyword aB1!c@2#
Dynamic Generation: Ranges and Choices

You can combine these features for maximum flexibility.

// Example: Generates a numeric string that is either 4, 8, or 12 characters long.
id := fastrand.RandomizerString("{RAND;4,8,12;DIGIT}")

// Example: Generates a token that is 10 to 20 characters long and is either hex or uppercase.
token := fastrand.RandomizerString("{RAND;10-20;HEX,ABU}")

// Example: Generates a contact identifier that is either a UUID or an email address.
contact := fastrand.RandomizerString("{RAND;UUID,EMAIL}")

The Configurable Engine: Full Customization

While the package-level functions are convenient, the real power of FastRand lies in creating and configuring your own Engine instances. This allows you to define isolated, reusable, and testable rule sets for data generation.

Creating a Custom Engine

The fastrand.NewEngine(...) function accepts a series of Option functions to build a custom configuration.

// A comprehensive example of a custom engine.
customEngine := fastrand.NewEngine(
    // --- Length Constraints ---
    fastrand.WithDefaultLength(20),
    fastrand.WithMinLength(10),
    fastrand.WithMaxLength(100),

    // --- Feature Toggles ---
    fastrand.WithRanges(false),         // Disable "5-10" syntax
    fastrand.WithKeywordChoices(true),  // Keep "HEX,UUID" syntax enabled

    // --- Encoding Rules ---
    fastrand.WithInputEncoding(fastrand.RandomizerEncodingURL), // ONLY accept URL-encoded tags
    fastrand.WithOutputEncoding(fastrand.RandomizerEncodingHTML), // HTML-escape literal output

    // --- Keyword & Charset Customization ---
    fastrand.WithDisabledKeywords("IPV6", "SPACE"), // Turn off specific keywords
    fastrand.WithCustomCharset("DIGIT", []byte("01")), // Make {RAND;..;DIGIT} produce binary
    fastrand.WithCustomKeyword("PRODUCT_ID", func(length int) []byte {
        return []byte("PROD-" + fastrand.String(length, fastrand.CharsAlphabetUpper))
    }),
)

// Now, use the highly customized engine:
template := "<item pid=\"{RAND;12;PRODUCT_ID}\" code=\"{RAND;16;DIGIT}\" />"
output := customEngine.RandomizerString(template)

// Possible Output:
// &lt;item pid=&#34;PROD-QWERASDFZXCV&#34; code=&#34;0110101100101101&#34; /&gt;
Complete List of Engine Options
Option Function Description Default
WithDefaultLength(int) Sets the fallback length if none is provided. 16
WithMinLength(int) Enforces a minimum length for generated data. 1
WithMaxLength(int) Enforces a maximum length for generated data. 99
WithRanges(bool) Enables/disables parsing of length ranges (5-10). true
WithLengthChoices(bool) Enables/disables parsing of length choices (5,10). true
WithKeywordChoices(bool) Enables/disables parsing of keyword choices (HEX,UUID). true
WithInputEncoding(RandomizerEncoding) Bitmask for recognized input encodings. URL | HTML
WithOutputEncoding(RandomizerEncoding) Sets encoding for literal output text. None
WithDisabledKeywords(...string) Disables one or more built-in keywords. (none)
WithMailProviders([]string) Sets a custom list of email domains. (embedded list)
WithCustomCharset(string, []byte) Overrides the character set for a keyword. (none)
WithCustomKeyword(string, func) Defines a new custom keyword. (none)

Concurrency

This library is fully concurrency-safe.

Both the PCG and ChaCha8 random sources provided by math/rand/v2 are designed for safe concurrent use across multiple goroutines. You can safely call any package-level function or use an Engine instance from multiple goroutines without needing external locks.

License

This project is licensed under the MIT License - see the LICENSE file for details. see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	CharsNull           = CharsList{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
	CharsSymbolChars    = CharsList("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")
	CharsAlphabetLower  = CharsList("abcdefghijklmnopqrstuvwxyz")
	CharsAlphabetUpper  = CharsList("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
	CharsDigits         = CharsList("0123456789")
	CharsSpace          = CharsList(" ")
	CharsAlphabet       = append(CharsAlphabetLower, CharsAlphabetUpper...)
	CharsAlphabetDigits = append(CharsAlphabet, CharsDigits...)
	CharsAll            = append(CharsAlphabetDigits, CharsSymbolChars...)
)
View Source
var (
	FastReader   io.Reader
	SecureReader io.Reader
)
View Source
var (
	SafeMailProviders []string
)

Functions

func Bool

func Bool() bool

func Byte

func Byte() byte

func Bytes

func Bytes(length int) []byte

func Choice

func Choice[T any](items []T) T

func ChoiceItemNullable

func ChoiceItemNullable[T any](slice []T) (*T, error)

func ChoiceKey

func ChoiceKey[T comparable, V any](items map[T]V) T

func ChoiceMultiple

func ChoiceMultiple[T any](items []T, count int) []T

func FastUUID

func FastUUID() ([]byte, error)

func Float64

func Float64() float64

func Hex

func Hex(length int) string

func IPv4

func IPv4() net.IP

func IPv6

func IPv6() net.IP

func Int

func Int(min, max int) int

func IntN

func IntN(n int) int

func MustFastUUID

func MustFastUUID() []byte

func MustSecureUUID

func MustSecureUUID() []byte

func Number

func Number[T number](min, max T) T

func NumberN

func NumberN[T number](n T) T

func Perm

func Perm(n int) []int

func Randomizer

func Randomizer(payload []byte) []byte

func RandomizerString

func RandomizerString(payload string) string

func SecureByte

func SecureByte() byte

func SecureBytes

func SecureBytes(length int) ([]byte, error)

func SecureFloat64

func SecureFloat64() float64

func SecureHex

func SecureHex(length int) (string, error)

func SecureIPv4

func SecureIPv4() (net.IP, error)

func SecureIPv6

func SecureIPv6() (net.IP, error)

func SecureInt

func SecureInt(min, max int) (int, error)

func SecureIntN

func SecureIntN(n int) (int, error)

func SecureNumber

func SecureNumber[T number](min, max T) (T, error)

func SecureNumberN

func SecureNumberN[T number](n T) (T, error)

func SecureString

func SecureString(length int, charset CharsList) (string, error)

func SecureUUID

func SecureUUID() ([]byte, error)

func Shuffle

func Shuffle(n int, swap func(i, j int))

func String

func String(length int, charset CharsList) string

Types

type CharsList

type CharsList []byte

type CustomKeywordGenerator

type CustomKeywordGenerator func(length int) []byte

type Engine

type Engine interface {
	Randomizer([]byte) []byte
	RandomizerString(string) string
}

type FastEngine

type FastEngine struct {
	// contains filtered or unexported fields
}

func NewEngine

func NewEngine(opts ...Option) *FastEngine

func (*FastEngine) Randomizer

func (e *FastEngine) Randomizer(payload []byte) []byte

func (*FastEngine) RandomizerString

func (e *FastEngine) RandomizerString(payload string) string

func (*FastEngine) Reset

func (e *FastEngine) Reset()

type Option

type Option func(*FastEngine)

func WithCustomCharset

func WithCustomCharset(keyword string, charset []byte) Option

func WithCustomKeyword

func WithCustomKeyword(keyword string, generator CustomKeywordGenerator) Option

func WithDefaultLength

func WithDefaultLength(length int) Option

func WithDisabledKeywords

func WithDisabledKeywords(keywords ...string) Option

func WithInputEncoding

func WithInputEncoding(encoding RandomizerEncoding) Option

func WithKeywordChoices

func WithKeywordChoices(enabled bool) Option

func WithLengthChoices

func WithLengthChoices(enabled bool) Option

func WithMailProviders

func WithMailProviders(providers []string) Option

func WithMaxLength

func WithMaxLength(length int) Option

func WithMinLength

func WithMinLength(length int) Option

func WithOutputEncoding

func WithOutputEncoding(encoding RandomizerEncoding) Option

func WithRanges

func WithRanges(enabled bool) Option

type RandomizerEncoding

type RandomizerEncoding int
const (
	RandomizerEncodingNone RandomizerEncoding = 0
	RandomizerEncodingURL  RandomizerEncoding = 1 << iota
	RandomizerEncodingHTML
)

Jump to

Keyboard shortcuts

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