codegen

package
v0.1.28 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2026 License: GPL-3.0 Imports: 6 Imported by: 0

README

codegen

A zero-dependency Go library for generating configurable-length random codes (numbers and letters). Designed for fulfillment services where unique, unpredictable order codes are required.

Features

  • Zero dependency — uses only the Go standard library
  • Thread-safe — a single Generator instance can be shared across the entire application
  • Cryptographically secure — uses crypto/rand instead of math/rand
  • Functional options — flexible and extensible API
  • OOP styleGenerator struct with a complete set of methods

Requirements

  • Go 1.21 or later

Installation

go get github.com/polarixa/replify/pkg/codegen

Quick Start

package main

import (
    "fmt"
    "log"

    "github.com/polarixa/replify/pkg/codegen"
)

func main() {
    // Create a generator for order codes.
    g, err := codegen.New(
        codegen.WithLength(10),
        codegen.WithCharset(codegen.CharsetAlphanumericUpper),
        codegen.WithPrefix("ORD-"),
    )
    if err != nil {
        log.Fatal(err)
    }

    code, err := g.Generate()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(code) // "ORD-A3BF9KP2XQ"
}

Creating a Generator

New — initialization with error handling
g, err := codegen.New(
    codegen.WithLength(12),
    codegen.WithCharset(codegen.CharsetAlphanumericUpper),
    codegen.WithPrefix("ORD-"),
    codegen.WithSuffix("-VN"),
)
MustNew — initialization at startup (panics on error)
// Declare at package level. Fail fast if the configuration is invalid.
var orderGen = codegen.MustNew(
    codegen.WithLength(12),
    codegen.WithCharset(codegen.CharsetAlphanumericUpper),
    codegen.WithPrefix("ORD-"),
)

Configuration Options

Option Description Default
WithLength(n int) Number of random characters (excluding prefix/suffix) 8
WithCharset(c Charset) Character set used for code generation CharsetAlphanumeric
WithCustomCharset(s string) Custom character set (duplicates removed automatically)
WithPrefix(s string) Static string prepended to every code ""
WithSuffix(s string) Static string appended to every code ""

Built-in Character Sets

Constant Contents Length
CharsetNumeric 0-9 10
CharsetAlphaLower a-z 26
CharsetAlphaUpper A-Z 26
CharsetAlpha a-z A-Z 52
CharsetAlphanumeric 0-9 a-z A-Z 62
CharsetAlphanumericUpper 0-9 A-Z 36
CharsetAlphanumericLower 0-9 a-z 36

API Reference

Generate a single code
code, err := g.Generate()
// "ORD-A3BF9KP2XQ"
Generate multiple codes
codes, err := g.GenerateN(100)
// ["ORD-A3BF9KP2XQ", "ORD-B7CD4MN8RT", ...]
Update the configuration
// Atomic update — the previous configuration remains unchanged if an error occurs.
err := g.SetOptions(
    codegen.WithLength(16),
    codegen.WithPrefix("INV-"),
)
Read the current configuration
opts := g.Options()
fmt.Printf("Length=%d, Charset=%s\n", opts.Length, opts.Charset)
Package-level convenience function (one-time generation)
// Convenient when the Generator does not need to be reused.
code, err := codegen.Generate(
    codegen.WithLength(10),
    codegen.WithCharset(codegen.CharsetNumeric),
)

Real-world Examples

Order Management (Fulfillment)
package order

import "github.com/polarixa/replify/pkg/codegen"

// Initialize once and reuse throughout the service.
var orderCodeGen = codegen.MustNew(
    codegen.WithLength(10),
    codegen.WithCharset(codegen.CharsetAlphanumericUpper),
    codegen.WithPrefix("ORD-"),
)

var invoiceCodeGen = codegen.MustNew(
    codegen.WithLength(8),
    codegen.WithCharset(codegen.CharsetNumeric),
    codegen.WithPrefix("INV-"),
    codegen.WithSuffix("-VN"),
)

// GenerateOrderCode generates an order code (thread-safe).
func GenerateOrderCode() (string, error) {
    return orderCodeGen.Generate()
    // "ORD-A3BF9KP2XQ"
}

// GenerateInvoiceCode generates an invoice code (thread-safe).
func GenerateInvoiceCode() (string, error) {
    return invoiceCodeGen.Generate()
    // "INV-84729163-VN"
}

// CreateOrders generates codes in bulk for batch processing.
func CreateOrders(count int) ([]string, error) {
    return orderCodeGen.GenerateN(count)
}
Using an Unambiguous Character Set
// Exclude visually ambiguous characters: 0/O and 1/I/l.
g, _ := codegen.New(
    codegen.WithLength(8),
    codegen.WithCustomCharset("23456789ABCDEFGHJKLMNPQRSTUVWXYZ"),
)
Integration with an HTTP Handler (Concurrent-Safe)
var gen = codegen.MustNew(
    codegen.WithLength(12),
    codegen.WithCharset(codegen.CharsetAlphanumericUpper),
    codegen.WithPrefix("TXN-"),
)

func CreateOrderHandler(w http.ResponseWriter, r *http.Request) {
    // Generator is safe for concurrent use across multiple requests.
    code, err := gen.Generate()
    if err != nil {
        http.Error(w, "internal error", http.StatusInternalServerError)
        return
    }
    // ... process the order using the generated code.
}

Thread Safety

Generator uses sync.Mutex to protect its internal state and relies on crypto/rand (which is already thread-safe) for random number generation. A single instance can be safely shared among thousands of concurrent goroutines.

// This is the recommended pattern — share a single Generator.
var gen = codegen.MustNew(codegen.WithLength(12))

// Safe to call concurrently from multiple goroutines.
go func() { gen.Generate() }()
go func() { gen.Generate() }()
go func() { gen.SetOptions(codegen.WithPrefix("NEW-")) }()

Running Tests

# Unit tests + race detector
go test -race ./...

# With coverage report
go test -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

# Benchmarks
go test -bench=. -benchmem ./...

Documentation

Overview

Package codegen provides a zero-dependency library for generating random codes (numbers and letters) with configurable length. It is designed for use in fulfillment services and is thread-safe for concurrent use by multiple goroutines.

Basic usage

g, err := codegen.New(
    codegen.WithLength(12),
    codegen.WithCharset(codegen.CharsetAlphanumericUpper),
    codegen.WithPrefix("ORD-"),
)
if err != nil {
    log.Fatal(err)
}

code, err := g.Generate()
// code == "ORD-A3BF9KP2XQ17"

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidLength is returned when Length is less than 1.
	ErrInvalidLength = errors.New("codegen: length must be greater than 0")

	// ErrEmptyCharset is returned when Charset is an empty string.
	ErrEmptyCharset = errors.New("codegen: charset must not be empty")

	// ErrInvalidCount is returned when the n argument passed to GenerateN is less than 1.
	ErrInvalidCount = errors.New("codegen: count must be greater than 0")
)

Sentinel errors returned by the library. They can be compared directly using errors.Is or the == operator.

Functions

func Generate

func Generate(opts ...Option) (string, error)

Generate is a package-level convenience function that creates a temporary Generator with the provided options and generates a single code.

It is suitable for one-off code generation. If you need to generate multiple codes, create a Generator with New and reuse it instead.

Example:

code, err := codegen.Generate(
    codegen.WithLength(10),
    codegen.WithCharset(codegen.CharsetNumeric),
)

Types

type Charset

type Charset string

Charset represents the set of characters used for random code generation. You can use one of the predefined constants or define your own character set with WithCustomCharset.

const (
	// CharsetNumeric contains only the digits 0-9.
	CharsetNumeric Charset = "0123456789"

	// CharsetAlphaLower contains only lowercase letters a-z.
	CharsetAlphaLower Charset = "abcdefghijklmnopqrstuvwxyz"

	// CharsetAlphaUpper contains only uppercase letters A-Z.
	CharsetAlphaUpper Charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// CharsetAlpha contains both lowercase and uppercase letters (a-z, A-Z).
	CharsetAlpha Charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// CharsetAlphanumeric contains digits, lowercase letters, and uppercase letters.
	// This is the default character set.
	CharsetAlphanumeric Charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// CharsetAlphanumericUpper contains digits and uppercase letters only.
	// It is commonly used for easy-to-read order codes.
	CharsetAlphanumericUpper Charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// CharsetAlphanumericLower contains digits and lowercase letters only.
	CharsetAlphanumericLower Charset = "0123456789abcdefghijklmnopqrstuvwxyz"
)

func (Charset) Len

func (c Charset) Len() int

Len returns the number of characters in the Charset.

func (Charset) String

func (c Charset) String() string

String returns the string representation of the Charset.

type Generator

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

Generator is the primary type for generating random codes. It uses crypto/rand to provide cryptographically secure randomness, making it suitable for order codes in fulfillment systems.

Generator is safe for concurrent use by multiple goroutines. A single instance can be shared across the entire application.

func MustNew

func MustNew(opts ...Option) *Generator

MustNew behaves like New but panics if an error occurs. It is intended for initialization during application startup, where invalid configuration should be detected immediately (fail fast).

Example:

var orderGen = codegen.MustNew(
    codegen.WithLength(12),
    codegen.WithCharset(codegen.CharsetAlphanumericUpper),
    codegen.WithPrefix("ORD-"),
)

func New

func New(opts ...Option) (*Generator, error)

New creates and returns a new Generator with the provided options. If no options are specified, the following defaults are applied:

  • Length: 8
  • Charset: CharsetAlphanumeric
  • Prefix: "" (empty)
  • Suffix: "" (empty)

Returns an error if any option is invalid:

  • ErrInvalidLength: if Length < 1
  • ErrEmptyCharset: if Charset is empty

Example:

g, err := codegen.New(
    codegen.WithLength(12),
    codegen.WithCharset(codegen.CharsetAlphanumericUpper),
    codegen.WithPrefix("ORD-"),
)
if err != nil {
    log.Fatal(err)
}

func (*Generator) Generate

func (g *Generator) Generate() (string, error)

Generate creates and returns a single random code using the current configuration. The total length of the returned string is: len(Prefix) + Length + len(Suffix).

Uses crypto/rand to ensure unpredictability. Safe for concurrent use by multiple goroutines.

Example:

code, err := g.Generate()
if err != nil {
    log.Fatal(err)
}
fmt.Println(code) // "ORD-A3BF9KP2XQ17"

func (*Generator) GenerateN

func (g *Generator) GenerateN(n int) ([]string, error)

GenerateN creates and returns a slice containing n independently generated random codes. Since each code is generated independently, duplicates are theoretically possible, although the probability is extremely low when using a sufficiently large charset and length.

Returns ErrInvalidCount if n < 1. Safe for concurrent use by multiple goroutines.

Example:

codes, err := g.GenerateN(100)
if err != nil {
    log.Fatal(err)
}
// codes contains a slice of 100 order codes

func (*Generator) Options

func (g *Generator) Options() Options

Options returns a snapshot copy of the Generator's current configuration. Modifying the returned value does not affect the Generator.

Safe for concurrent use by multiple goroutines.

func (*Generator) SetOptions

func (g *Generator) SetOptions(opts ...Option) error

SetOptions atomically updates the Generator configuration. If any provided option is invalid, the existing configuration remains unchanged and an error is returned (no partial update).

Safe for concurrent use by multiple goroutines.

Example:

err := g.SetOptions(
    codegen.WithLength(16),
    codegen.WithPrefix("INV-"),
)

type Option

type Option func(*Options)

Option is a functional option used to configure a Generator. Use the WithXxx helper functions to create Options and pass them to New or SetOptions.

func WithCharset

func WithCharset(charset Charset) Option

WithCharset sets the character set used for random code generation. It is recommended to use one of the predefined Charset constants provided by this package.

Example:

g, _ := codegen.New(codegen.WithCharset(codegen.CharsetNumeric))

func WithCustomCharset

func WithCustomCharset(chars string) Option

WithCustomCharset sets a custom character set from an arbitrary string. Duplicate characters are removed to ensure a uniform distribution.

Example:

// Use only characters that are easy to distinguish visually.
g, _ := codegen.New(codegen.WithCustomCharset("23456789ABCDEFGHJKLMNPQRSTUVWXYZ"))

func WithLength

func WithLength(length int) Option

WithLength sets the number of random characters for each generated code. The value must be greater than 0; otherwise, New and SetOptions will return ErrInvalidLength.

Example:

g, _ := codegen.New(codegen.WithLength(12))

func WithPrefix

func WithPrefix(prefix string) Option

WithPrefix sets the static string prepended to every generated code. The Prefix is not included in Length.

Example:

g, _ := codegen.New(codegen.WithPrefix("ORD-"))
// Generates: "ORD-A3BF9KP2"

func WithSuffix

func WithSuffix(suffix string) Option

WithSuffix sets the static string appended to every generated code. The Suffix is not included in Length.

Example:

g, _ := codegen.New(codegen.WithSuffix("-VN"))
// Generates: "A3BF9KP2-VN"

type Options

type Options struct {
	// Length is the number of random characters in each generated code,
	// excluding the Prefix and Suffix.
	Length int

	// Charset is the character set used for random code generation.
	Charset Charset

	// Prefix is a static string prepended to every generated code.
	Prefix string

	// Suffix is a static string appended to every generated code.
	Suffix string
}

Options contains the complete configuration for a Generator. All fields have valid default values provided by defaultOptions.

Jump to

Keyboard shortcuts

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