nanoid

package module
v1.22.0 Latest Latest
Warning

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

Go to latest
Published: Dec 26, 2024 License: Apache-2.0 Imports: 11 Imported by: 1

README

nanoid Nano ID logo by Anton Lovchikov

CI Go Quality Gate Status GitHub issues Go Reference Go Report Card CodeQL

A simple, fast, and efficient Go implementation of Nano ID, a tiny, secure, URL-friendly, unique string ID generator.

Please see the godoc for detailed documentation.


Features

  • Short & Unique IDs: Generates compact and collision-resistant identifiers.
  • Cryptographically Secure: Utilizes Go's crypto/rand and x/crypto/chacha20 stream cypher package for generating cryptographically secure random numbers. This guarantees that the generated IDs are both unpredictable and suitable for security-sensitive applications.
  • Customizable:
    • Define your own set of characters for ID generation with a minimum length of 2 characters and maximum length of 256 characters.
    • Define your own random number generator.
    • Unicode and ASCII alphabets supported.
  • Concurrency Safe: Designed to be safe for use in concurrent environments.
  • High Performance: Optimized with buffer pooling to minimize allocations and enhance speed.
  • Optimized for Low Allocations: Carefully structured to minimize heap allocations, reducing memory overhead and improving cache locality. This optimization is crucial for applications where performance and resource usage are critical.
    • 1 allocs/op for ASCII and Unicode alphabets regardless of alphabet size or generated ID length.
  • Zero Dependencies: Lightweight implementation with no external dependencies beyond the standard library.
  • Supports io.Reader Interface:
    • The Nano ID generator satisfies the io.Reader interface, allowing it to be used interchangeably with any io.Reader implementations.
    • Developers can utilize the Nano ID generator in contexts such as streaming data processing, pipelines, and other I/O-driven operations.

Please see the Nano ID CLI for a command-line interface (CLI) that uses this package to generate Nano IDs.


Installation

Using go get

To install the Nano ID package, run the following command:

go get -u github.com/sixafter/nanoid

To use the NanoID package in your Go project, import it as follows:

import "github.com/sixafter/nanoid"

Usage

Basic Usage with Default Settings

The simplest way to generate a Nano ID is by using the default settings. This utilizes the predefined alphabet and default ID length.

package main

import (
  "fmt"
  
  "github.com/sixafter/nanoid"
)

func main() {
  id, err := nanoid.New() 
  if err != nil {
    panic(err)
  }
  fmt.Println("Generated ID:", id)
}

Output:

Generated ID: mGbzQkkPBidjL4IP_MwBM
Generating a Nano ID with Custom length

Generate a NanoID with a custom length.

package main

import (
  "fmt"
  
  "github.com/sixafter/nanoid"
)

func main() {
  id, err := nanoid.NewWithLength(10)
  if err != nil {
    panic(err)
  }
  fmt.Println("Generated ID:", id)
}

Output:

Generated ID: 1A3F5B7C9D
Using io.Reader Interface

Here's a simple example demonstrating how to use the Nano ID generator as an io.Reader:

package main

import (
  "fmt"
  "io"
  
  "github.com/sixafter/nanoid"
)

func main() {
	// Nano ID default length is 21
	buf := make([]byte, nanoid.DefaultLength)

	// Read a Nano ID into the buffer
	_, err := nanoid.Read(buf)
	if err != nil && err != io.EOF {
		panic(err)
	}

	// Convert the byte slice to a string
	id := string(buf)
	fmt.Printf("Generated ID: %s\n", id)
}

Output:

Generated ID: 2mhTvy21bBZhZcd80ZydM
Customizing the Alphabet and ID Length

You can customize the alphabet by using the WithAlphabet option and generate an ID with a custom length.

package main

import (
	"fmt"

	"github.com/sixafter/nanoid"
)

func main() {
	// Define a custom alphabet
	alphabet := "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

	// Create a new generator with custom alphabet and length hint
	gen, err := nanoid.NewGenerator(
		nanoid.WithAlphabet(alphabet),
		nanoid.WithLengthHint(10),
	)
	if err != nil {
		fmt.Println("Error creating Nano ID generator:", err)
		return
	}

	// Generate a Nano ID using the custom generator
	id, err := gen.New(10)
	if err != nil {
		fmt.Println("Error generating Nano ID:", err)
		return
	}

	fmt.Println("Generated ID:", id)
}

Output"

Generated ID: G5J8K2M0QZ
Customizing the Random Number Generator

You can customize the random number generator by using the WithRandReader option and generate an ID.

package main

import (
	"crypto/rand"
	"fmt"

	"github.com/sixafter/nanoid"
)

func main() {
	// Create a new generator with custom random number generator
	gen, err := nanoid.NewGenerator(
		nanoid.WithRandReader(rand.Reader),
	)
	if err != nil {
		fmt.Println("Error creating Nano ID generator:", err)
		return
	}

	// Generate a Nano ID using the custom generator
	id, err := gen.New(nanoid.DefaultLength)
	if err != nil {
		fmt.Println("Error generating Nano ID:", err)
		return
	}

	fmt.Println("Generated ID:", id)
}

Output"

Generated ID: A8I8K3J0QY

Performance Optimizations

Buffer Pooling with sync.Pool

The nanoid generator utilizes sync.Pool to manage byte slice buffers efficiently. This approach minimizes memory allocations and enhances performance, especially in high-concurrency scenarios.

How It Works:

  • Storing Pointers: sync.Pool stores pointers to []byte (or []rune if Unicode) slices (*[]byte) instead of the slices themselves. This avoids unnecessary allocations and aligns with best practices for using sync.Pool.
  • Zeroing Buffers: Before returning buffers to the pool, they are zeroed out to prevent data leaks.
Struct Optimization

The generator struct is optimized for memory alignment and size by ordering from largest to smallest to minimize padding and optimize memory usage.

Execute Benchmarks:

Run the benchmarks using the go test command with the bench make target:

make bench
Interpreting Results:

Sample output might look like this:

Expand to see results
go test -bench=. -benchmem -memprofile=mem.out -cpuprofile=cpu.out
goos: darwin
goarch: arm64
pkg: github.com/sixafter/nanoid
cpu: Apple M4 Max
BenchmarkNanoIDAllocations-16                           15003954                76.30 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDAllocationsConcurrent-16                 74179202                15.76 ns/op           24 B/op          1 allocs/op
BenchmarkGenerator_Read_DefaultLength-16                16803123                68.10 ns/op           24 B/op          1 allocs/op
BenchmarkGenerator_Read_VaryingBufferSizes/BufferSize_2-16              33585614                36.13 ns/op            2 B/op          1 allocs/op
BenchmarkGenerator_Read_VaryingBufferSizes/BufferSize_3-16              31765290                38.20 ns/op            3 B/op          1 allocs/op
BenchmarkGenerator_Read_VaryingBufferSizes/BufferSize_5-16              28791708                42.14 ns/op            5 B/op          1 allocs/op
BenchmarkGenerator_Read_VaryingBufferSizes/BufferSize_13-16             22228155                55.78 ns/op           16 B/op          1 allocs/op
BenchmarkGenerator_Read_VaryingBufferSizes/BufferSize_21-16             18243597                65.63 ns/op           24 B/op          1 allocs/op
BenchmarkGenerator_Read_VaryingBufferSizes/BufferSize_34-16             13976239                86.27 ns/op           48 B/op          1 allocs/op
BenchmarkGenerator_Read_ZeroLengthBuffer-16                             816275398                1.372 ns/op           0 B/op          0 allocs/op
BenchmarkGenerator_Read_Concurrent/Concurrency_1-16                     17746567                66.30 ns/op           24 B/op          1 allocs/op
BenchmarkGenerator_Read_Concurrent/Concurrency_2-16                     33351552                36.08 ns/op           24 B/op          1 allocs/op
BenchmarkGenerator_Read_Concurrent/Concurrency_4-16                     55830726                21.93 ns/op           24 B/op          1 allocs/op
BenchmarkGenerator_Read_Concurrent/Concurrency_8-16                     60704806                18.97 ns/op           24 B/op          1 allocs/op
BenchmarkGenerator_Read_Concurrent/Concurrency_16-16                    67446042                16.91 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen2/IDLen8-16                  25284205                46.18 ns/op            8 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen2/IDLen16-16                 20124421                58.75 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen2/IDLen21-16                 18030165                65.83 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen2/IDLen32-16                 14527756                82.23 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen2/IDLen64-16                  8959059               134.7 ns/op            64 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen2/IDLen128-16                 5327983               225.5 ns/op           128 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen16/IDLen8-16                 24694173                45.10 ns/op            8 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen16/IDLen16-16                20262411                57.76 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen16/IDLen21-16                18349347                65.79 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen16/IDLen32-16                14576307                81.71 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen16/IDLen64-16                 8961514               133.6 ns/op            64 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen16/IDLen128-16                5336977               224.3 ns/op           128 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen32/IDLen8-16                 26897259                46.21 ns/op            8 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen32/IDLen16-16                20310639                58.69 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen32/IDLen21-16                17752453                67.27 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen32/IDLen32-16                14871600                80.86 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen32/IDLen64-16                 9064250               134.2 ns/op            64 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen32/IDLen128-16                5340874               223.6 ns/op           128 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen64/IDLen8-16                 26052786                45.81 ns/op            8 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen64/IDLen16-16                20089396                57.76 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen64/IDLen21-16                18227050                65.65 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen64/IDLen32-16                14711966                81.99 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen64/IDLen64-16                 8971347               134.5 ns/op            64 B/op          1 allocs/op
BenchmarkNanoIDGeneration/ASCII_AlphabetLen64/IDLen128-16                5296887               226.6 ns/op           128 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen2/IDLen8-16                16784506                70.18 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen2/IDLen16-16               11497441               104.4 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen2/IDLen21-16                9549919               125.2 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen2/IDLen32-16                6733585               178.0 ns/op            80 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen2/IDLen64-16                3697659               326.2 ns/op           144 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen2/IDLen128-16               1986321               607.8 ns/op           289 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen16/IDLen8-16               17139867                69.70 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen16/IDLen16-16              11514620               104.0 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen16/IDLen21-16               9670254               123.7 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen16/IDLen32-16               6933122               173.9 ns/op            80 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen16/IDLen64-16               3671619               324.5 ns/op           144 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen16/IDLen128-16              1984659               601.5 ns/op           289 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen32/IDLen8-16               17377945                68.67 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen32/IDLen16-16              11687414               103.8 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen32/IDLen21-16               9423592               126.0 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen32/IDLen32-16               6661424               179.6 ns/op            80 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen32/IDLen64-16               3693400               322.7 ns/op           144 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen32/IDLen128-16              1993962               604.1 ns/op           289 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen64/IDLen8-16               17084515                69.71 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen64/IDLen16-16              11476266               103.1 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen64/IDLen21-16               9785174               125.6 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen64/IDLen32-16               6641458               178.9 ns/op            80 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen64/IDLen64-16               3680024               325.8 ns/op           144 B/op          1 allocs/op
BenchmarkNanoIDGeneration/Unicode_AlphabetLen64/IDLen128-16              1970880               608.1 ns/op           289 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen2/IDLen8-16          155731814                7.966 ns/op           8 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen2/IDLen16-16         100000000               10.72 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen2/IDLen21-16         88434433                12.91 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen2/IDLen32-16         76901302                15.83 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen2/IDLen64-16         44088199                26.29 ns/op           64 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen2/IDLen128-16        25929686                45.83 ns/op          128 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen16/IDLen8-16         159970467                7.688 ns/op           8 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen16/IDLen16-16        100000000               10.46 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen16/IDLen21-16        91863391                12.60 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen16/IDLen32-16        71162065                15.79 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen16/IDLen64-16        44062299                26.30 ns/op           64 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen16/IDLen128-16       26455730                44.79 ns/op          128 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen32/IDLen8-16         162121165                7.687 ns/op           8 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen32/IDLen16-16        100000000               10.86 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen32/IDLen21-16        83806197                13.03 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen32/IDLen32-16        75761760                15.57 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen32/IDLen64-16        45690134                25.44 ns/op           64 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen32/IDLen128-16       26845486                44.60 ns/op          128 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen64/IDLen8-16         160724536                7.605 ns/op           8 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen64/IDLen16-16        100000000               10.66 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen64/IDLen21-16        91057120                12.44 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen64/IDLen32-16        75076638                15.30 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen64/IDLen64-16        45273408                26.00 ns/op           64 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/ASCII_AlphabetLen64/IDLen128-16       26638818                44.49 ns/op          128 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen2/IDLen8-16        86501292                12.93 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen2/IDLen16-16       54813188                20.64 ns/op           48 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen2/IDLen21-16       53420488                22.20 ns/op           48 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen2/IDLen32-16       36231016                31.31 ns/op           80 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen2/IDLen64-16       22430011                53.27 ns/op          144 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen2/IDLen128-16      12645932                96.45 ns/op          288 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen16/IDLen8-16       93198150                12.98 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen16/IDLen16-16      58279538                19.86 ns/op           48 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen16/IDLen21-16      55201494                21.39 ns/op           48 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen16/IDLen32-16      37473552                31.02 ns/op           80 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen16/IDLen64-16      22530309                53.32 ns/op          144 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen16/IDLen128-16             12306376                96.18 ns/op          288 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen32/IDLen8-16               88192876                12.87 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen32/IDLen16-16              57457620                20.01 ns/op           48 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen32/IDLen21-16              53846470                21.74 ns/op           48 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen32/IDLen32-16              37763508                31.43 ns/op           80 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen32/IDLen64-16              22099260                54.05 ns/op          144 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen32/IDLen128-16             12431437                96.13 ns/op          288 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen64/IDLen8-16               84577526                12.84 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen64/IDLen16-16              58122990                19.93 ns/op           48 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen64/IDLen21-16              52644855                21.77 ns/op           48 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen64/IDLen32-16              37568679                31.45 ns/op           80 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen64/IDLen64-16              22077678                54.60 ns/op          144 B/op          1 allocs/op
BenchmarkNanoIDGenerationParallel/Unicode_AlphabetLen64/IDLen128-16             12427960                96.53 ns/op          288 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen2/IDLen8-16          24682723                45.65 ns/op            8 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen2/IDLen16-16         19997860                59.69 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen2/IDLen21-16         17316693                69.90 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen2/IDLen32-16         13858519                86.02 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen2/IDLen64-16          8383051               144.3 ns/op            64 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen2/IDLen128-16         4923039               243.1 ns/op           128 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen16/IDLen8-16         25041670                46.75 ns/op            8 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen16/IDLen16-16        19813886                60.98 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen16/IDLen21-16        17404220                69.12 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen16/IDLen32-16        13892030                85.15 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen16/IDLen64-16         8509674               141.9 ns/op            64 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen16/IDLen128-16        4921491               241.0 ns/op           128 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen32/IDLen8-16         25172382                47.19 ns/op            8 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen32/IDLen16-16        19663951                60.46 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen32/IDLen21-16        17468212                68.51 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen32/IDLen32-16        14062369                85.35 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen32/IDLen64-16         8480640               141.5 ns/op            64 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen32/IDLen128-16        5044694               238.8 ns/op           128 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen64/IDLen8-16         26560914                45.30 ns/op            8 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen64/IDLen16-16        19941325                60.39 ns/op           16 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen64/IDLen21-16        17160159                68.94 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen64/IDLen32-16        13838980                86.89 ns/op           32 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen64/IDLen64-16         8455816               140.1 ns/op            64 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/ASCII_AlphabetLen64/IDLen128-16        5122021               234.6 ns/op           128 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen2/IDLen8-16        16634562                71.56 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen2/IDLen16-16       11221044               107.0 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen2/IDLen21-16        9227674               129.0 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen2/IDLen32-16        6767592               178.3 ns/op            80 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen2/IDLen64-16        3574780               333.7 ns/op           144 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen2/IDLen128-16       1922041               628.0 ns/op           288 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen16/IDLen8-16       16603988                70.65 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen16/IDLen16-16      11450854               106.3 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen16/IDLen21-16       9321528               128.2 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen16/IDLen32-16       6649005               182.6 ns/op            80 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen16/IDLen64-16       3578170               333.0 ns/op           144 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen16/IDLen128-16      1946996               617.6 ns/op           288 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen32/IDLen8-16       16661652                71.52 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen32/IDLen16-16      11298946               106.5 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen32/IDLen21-16       9353600               128.5 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen32/IDLen32-16       6632572               179.0 ns/op            80 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen32/IDLen64-16       3584874               333.7 ns/op           144 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen32/IDLen128-16      1914860               624.4 ns/op           288 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen64/IDLen8-16       16383211                70.89 ns/op           24 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen64/IDLen16-16      11173053               107.2 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen64/IDLen21-16       9277276               128.6 ns/op            48 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen64/IDLen32-16       6546392               182.6 ns/op            80 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen64/IDLen64-16       3611689               334.5 ns/op           144 B/op          1 allocs/op
BenchmarkNanoIDWithVaryingAlphabetLengths/Unicode_AlphabetLen64/IDLen128-16      1939897               618.9 ns/op           288 B/op          1 allocs/op
PASS
ok      github.com/sixafter/nanoid      210.925s
  • ns/op: Nanoseconds per operation. Lower values indicate faster performance.
  • B/op: Bytes allocated per operation. Lower values indicate more memory-efficient code.
  • allocs/op: Number of memory allocations per operation. Fewer allocations generally lead to better performance.

ID Generation

Nano ID generates unique identifiers based on the following:

  1. Random Byte Generation: Nano ID generates a sequence of random bytes using a secure random source (e.g., crypto/rand.Reader).
  2. Mapping to Alphabet: Each random byte is mapped to a character in a predefined alphabet to form the final ID.
  3. Uniform Distribution: To ensure that each character in the alphabet has an equal probability of being selected, Nano ID employs techniques to avoid bias, especially when the alphabet size isn't a power of two.

Custom Alphabet Constraints

  1. Alphabet Lengths:
    • At Least Two Characters: The custom alphabet must contain at least two unique characters. An alphabet with fewer than two characters cannot produce IDs with sufficient variability or randomness.
    • Maximum Length 256 Characters: The implementation utilizes a rune-based approach, where each character in the alphabet is represented by a single rune. This allows for a broad range of unique characters, accommodating alphabets with up to 256 distinct runes. Attempting to use an alphabet with more than 256 runes will result in an error.
  2. Uniqueness of Characters:
    • All Characters Must Be Unique. Duplicate characters in the alphabet can introduce biases in ID generation and compromise the randomness and uniqueness of the IDs. The generator enforces uniqueness by checking for duplicates during initialization. If duplicates are detected, it will return an ErrDuplicateCharacters error.
  3. Character Encoding:
    • Support for ASCII and Unicode: The generator accepts alphabets containing Unicode characters, allowing you to include a wide range of symbols, emojis, or characters from various languages.

Determining Collisions

To determine the practical length for a NanoID for your use cases, see the collision time calculator here.


Contributing

Contributions are welcome. See CONTRIBUTING


License

This project is licensed under the Apache 2.0 License. See LICENSE file.

Documentation

Index

Constants

View Source
const (
	// DefaultAlphabet defines the standard set of characters used for Nano ID generation.
	// It includes uppercase and lowercase English letters, digits, and the characters
	// '_' and '-'. This selection aligns with the Nano ID specification, ensuring
	// a URL-friendly and easily readable identifier.
	//
	// Example: "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	DefaultAlphabet = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// DefaultLength specifies the default number of characters in a generated Nano ID.
	// A length of 21 characters provides a high level of uniqueness while maintaining
	// brevity, making it suitable for most applications requiring unique identifiers.
	DefaultLength = 21

	// MinAlphabetLength sets the minimum permissible number of unique characters
	// in the alphabet used for Nano ID generation. An alphabet with fewer than
	// 2 characters would not provide sufficient variability for generating unique IDs,
	// making this a lower bound to ensure meaningful ID generation.
	//
	// Example: An alphabet like "AB" is acceptable, but "A" is not.
	MinAlphabetLength = 2

	// MaxAlphabetLength defines the maximum allowable number of unique characters
	// in the alphabet for Nano ID generation. This upper limit ensures that the
	// generator operates within reasonable memory and performance constraints,
	// preventing excessively large alphabets that could degrade performance or
	// complicate index calculations.
	MaxAlphabetLength = 256
)

Variables

View Source
var (
	// ErrDuplicateCharacters is returned when the provided alphabet contains duplicate characters.
	ErrDuplicateCharacters = errors.New("duplicate characters in alphabet")

	// ErrExceededMaxAttempts is returned when the maximum number of attempts to perform
	// an operation, such as generating a unique ID, has been exceeded.
	ErrExceededMaxAttempts = errors.New("exceeded maximum attempts")

	// ErrInvalidLength is returned when a specified length value for an operation is invalid.
	ErrInvalidLength = errors.New("invalid length")

	// ErrInvalidAlphabet is returned when the provided alphabet for generating IDs is invalid.
	ErrInvalidAlphabet = errors.New("invalid alphabet")

	// ErrNonUTF8Alphabet is returned when the provided alphabet contains non-UTF-8 characters.
	ErrNonUTF8Alphabet = errors.New("alphabet contains invalid UTF-8 characters")

	// ErrAlphabetTooShort is returned when the provided alphabet has fewer than 2 characters.
	ErrAlphabetTooShort = errors.New("alphabet length is less than 2")

	// ErrAlphabetTooLong is returned when the provided alphabet exceeds 256 characters.
	ErrAlphabetTooLong = errors.New("alphabet length exceeds 256")

	// ErrNilRandReader is returned when the random number generator (rand.Reader) is nil,
	// preventing the generation of random values.
	ErrNilRandReader = errors.New("nil random reader")

	// ErrNilPointer is returned when a nil pointer is passed to a function that does not accept nil pointers.
	ErrNilPointer = errors.New("nil pointer")
)
View Source
var EmptyID = ID("")

EmptyID represents an empty Nano ID.

Functions

func Read added in v1.14.0

func Read(b []byte) (n int, err error)

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

Reader is the interface that wraps the basic Read method.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == EOF or err == nil. The next Read should return 0, EOF.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-nil error if some error condition is known, such as EOF.

Implementations of Read are discouraged from returning a zero byte count with a nil error, except when len(p) == 0. Callers should treat a return of 0 and nil as indicating that nothing happened; in particular it does not indicate EOF.

Implementations must not retain p.

Types

type Config added in v1.5.0

type Config interface {
	// AlphabetLen returns the number of unique characters in the provided alphabet.
	//
	// This length determines the range of indices for selecting characters during ID generation.
	// Using uint16 allows for alphabets up to 65,535 characters.
	AlphabetLen() uint16

	// BaseMultiplier returns the foundational multiplier used in buffer size calculations.
	//
	// It is based on the logarithm of the intended ID length (LengthHint) plus 2.
	// This helps scale the buffer size appropriately with different ID lengths.
	BaseMultiplier() int

	// BitsNeeded returns the minimum number of bits required to represent all possible indices of the alphabet.
	//
	// This value is crucial for generating random numbers that map uniformly to the alphabet indices without bias.
	BitsNeeded() uint

	// BufferMultiplier returns the combined multiplier used in the buffer size calculation.
	//
	// It adds a fraction of the scaling factor to the base multiplier to fine-tune the buffer size,
	// considering both the ID length and the alphabet size.
	BufferMultiplier() int

	// BufferSize returns the total size of the buffer (in bytes) used for generating random data.
	//
	// The buffer size is calculated to balance efficiency and performance,
	// minimizing calls to the random number generator by reading larger chunks of random data at once.
	BufferSize() int

	// ByteAlphabet returns the slice of bytes representing the alphabet,
	// used when the alphabet consists solely of ASCII characters.
	//
	// For non-ASCII alphabets, this returns nil, and RuneAlphabet is used instead.
	ByteAlphabet() []byte

	// BytesNeeded returns the number of bytes required to store the BitsNeeded for each character in the ID.
	//
	// It rounds up BitsNeeded to the nearest byte, ensuring sufficient space for random data generation.
	BytesNeeded() uint

	// IsASCII returns true if the alphabet consists solely of ASCII characters.
	//
	// This allows for optimization in processing, using bytes instead of runes for ID generation.
	IsASCII() bool

	// IsPowerOfTwo returns true if the length of the alphabet is a power of two.
	//
	// When true, random index selection can be optimized using bitwise operations,
	// such as bitwise AND with the mask, improving performance.
	IsPowerOfTwo() bool

	// LengthHint returns the intended length of the IDs to be generated.
	//
	// This hint is used in calculations to adjust buffer sizes and scaling factors accordingly.
	LengthHint() uint16

	// MaxBytesPerRune represents the maximum number of bytes required to encode
	// any rune in the alphabet using UTF-8 encoding.
	//
	// This value is computed during
	// configuration based on the provided alphabet and is used to preallocate the
	// buffer size in the newUnicode function. By accurately estimating the buffer size,
	// we ensure efficient string building without unnecessary memory allocations
	// or buffer resizing.
	//
	// For example, if the alphabet includes only ASCII and Latin-1 characters, each rune
	// requires at most 2 bytes. However, if the alphabet includes emojis or other
	// multibyte characters, this value could be up to 4 bytes.
	MaxBytesPerRune() int

	// Mask returns the bitmask used to extract the necessary bits from randomly generated bytes.
	//
	// The mask is essential for efficiently mapping random values to valid alphabet indices,
	// ensuring uniform distribution and preventing bias.
	Mask() uint

	// RandReader returns the source of randomness used for generating IDs.
	//
	// It is typically a cryptographically secure random number generator (e.g., crypto/rand.Reader).
	RandReader() io.Reader

	// RuneAlphabet returns the slice of runes representing the alphabet.
	//
	// This is used for ID generation when the alphabet includes non-ASCII (multibyte) characters,
	// allowing support for a wider range of characters.
	RuneAlphabet() []rune

	// ScalingFactor returns the scaling factor used to adjust the buffer size.
	//
	// It balances the influence of the alphabet size and the intended ID length,
	// ensuring efficient random data generation without excessive memory usage.
	ScalingFactor() int
}

Config holds the runtime configuration for the Nano ID generator.

It is immutable after initialization and provides all the necessary parameters for generating unique IDs efficiently and securely.

type ConfigOptions added in v1.10.0

type ConfigOptions struct {
	// RandReader is the source of randomness used for generating IDs.
	// By default, it uses x/crypto/prng/Reader, which provides cryptographically secure random bytes.
	RandReader io.Reader

	// Alphabet is the set of characters used to generate the Nano ID.
	// It must be a valid UTF-8 string containing between 2 and 256 unique characters.
	// Using a diverse and appropriately sized alphabet ensures the uniqueness and randomness of the generated IDs.
	Alphabet string

	// LengthHint specifies a typical or default length for generated IDs.
	LengthHint uint16
}

ConfigOptions holds the configurable options for the Interface. It is used with the Function Options pattern.

type Configuration added in v1.5.0

type Configuration interface {
	// Config returns the runtime configuration of the generator.
	Config() Config
}

Configuration defines the interface for retrieving generator configuration.

type ID added in v1.18.0

type ID string

ID represents a Nano ID as a string.

func Must added in v1.10.0

func Must() ID

Must generates a new Nano ID using the default length specified by `DefaultLength`. It returns the generated ID as a string. If an error occurs during ID generation, it panics. This function simplifies safe initialization of global variables holding pre-generated Nano IDs.

Usage:

id := nanoid.Must()
fmt.Println("Generated ID:", id)

func MustWithLength added in v1.10.0

func MustWithLength(length int) ID

MustWithLength generates a new Nano ID of the specified length. It returns the generated ID as a string. If an error occurs during ID generation, it panics. The 'length' parameter specifies the number of characters in the generated ID. This function simplifies safe initialization of global variables holding pre-generated Nano IDs.

Parameters:

  • length int: The number of characters for the generated ID.

Usage:

id := nanoid.MustWithLength(30)
fmt.Println("Generated ID:", id)

func New added in v1.3.0

func New() (ID, error)

New generates a new Nano ID using the default length specified by `DefaultLength`. It returns the generated ID as a string and any error encountered during the generation.

Usage:

id, err := nanoid.New()
if err != nil {
    // handle error
}
fmt.Println("Generated ID:", id)

func NewWithLength added in v1.10.0

func NewWithLength(length int) (ID, error)

NewWithLength generates a new Nano ID of the specified length. It returns the generated ID as a string and any error encountered during the generation.

Parameters:

  • length int: The number of characters for the generated ID.

Usage:

id, err := nanoid.NewWithLength(21)
if err != nil {
    // handle error
}
fmt.Println("Generated ID:", id)

func (*ID) Compare added in v1.18.0

func (id *ID) Compare(other ID) int

Compare compares two IDs lexicographically and returns an integer. The result will be 0 if id==other, -1 if id < other, and +1 if id > other.

Parameters:

  • other ID: The ID to compare against.

Returns:

  • int: An integer indicating the comparison result.

Usage:

id1 := ID("V1StGXR8_Z5jdHi6B-myT")
id2 := ID("V1StGXR8_Z5jdHi6B-myT")
result := id1.Compare(id2)
fmt.Println(result) // Output: 0

func (*ID) IsEmpty added in v1.18.0

func (id *ID) IsEmpty() bool

IsEmpty returns true if the ID is an empty ID (EmptyID)

func (*ID) MarshalBinary added in v1.18.0

func (id *ID) MarshalBinary() ([]byte, error)

MarshalBinary converts the ID to a byte slice. It implements the encoding.BinaryMarshaler interface, enabling the ID to be marshaled into binary formats for efficient storage or transmission.

Returns:

  • A byte slice containing the ID.
  • An error if the marshaling fails.

Example:

id := Must()
binaryData, err := id.MarshalBinary()
if err != nil {
    log.Fatal(err)
}
fmt.Println(binaryData) // Output: [86 49 83 116 71 88 82 56 95 90 ...]

func (*ID) MarshalText added in v1.18.0

func (id *ID) MarshalText() ([]byte, error)

MarshalText converts the ID to a byte slice. It implements the encoding.TextMarshaler interface, enabling the ID to be marshaled into text-based formats such as XML and YAML.

Returns:

  • A byte slice containing the ID.
  • An error if the marshaling fails.

Example:

id := Must()
text, err := id.MarshalText()
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(text)) // Output: V1StGXR8_Z5jdHi6B-myT

func (*ID) String added in v1.18.0

func (id *ID) String() string

String returns the string representation of the ID. It implements the fmt.Stringer interface, allowing the ID to be used seamlessly with fmt package functions like fmt.Println and fmt.Printf.

Example:

id := Must()
fmt.Println(id) // Output: V1StGXR8_Z5jdHi6B-myT

func (*ID) UnmarshalBinary added in v1.18.0

func (id *ID) UnmarshalBinary(data []byte) error

UnmarshalBinary parses a byte slice and assigns the result to the ID. It implements the encoding.BinaryUnmarshaler interface, allowing the ID to be unmarshaled from binary formats.

Parameters:

  • data: A byte slice containing the binary ID data.

Returns:

  • An error if the unmarshaling fails.

Example:

var id ID
err := id.UnmarshalBinary([]byte{86, 49, 83, 116, 71, 88, 82, 56, 95, 90}) // "V1StGXR8_Z5jdHi6B-myT"
if err != nil {
    log.Fatal(err)
}
fmt.Println(id) // Output: V1StGXR8_Z5jdHi6B-myT

func (*ID) UnmarshalText added in v1.18.0

func (id *ID) UnmarshalText(text []byte) error

UnmarshalText parses a byte slice and assigns the result to the ID. It implements the encoding.TextUnmarshaler interface, allowing the ID to be unmarshaled from text-based formats.

Parameters:

  • text: A byte slice containing the ID data.

Returns:

  • An error if the unmarshaling fails.

Example:

var id ID
err := id.UnmarshalText([]byte("new-id"))
if err != nil {
    log.Fatal(err)
}
fmt.Println(id) // Output: new-id

type Interface added in v1.21.0

type Interface interface {
	// New generates and returns a new Nano ID as a string with the specified length.
	// The 'length' parameter determines the number of characters in the generated ID.
	// Returns an error if the ID generation fails due to issues like insufficient randomness.
	//
	// Usage:
	//   id, err := generator.New(21)
	//   if err != nil {
	//       // handle error
	//   }
	//   fmt.Println("Generated ID:", id)
	New(length int) (ID, error)

	// Read fills the provided byte slice 'p' with random data, reading up to len(p) bytes.
	// Returns the number of bytes read and any error encountered during the read operation.
	//
	// Implements the io.Reader interface, allowing the Interface to be used wherever an io.Reader is accepted.
	// This can be useful for directly obtaining random bytes or integrating with other components that consume random data.
	//
	// Usage:
	//   buffer := make([]byte, 21)
	//   n, err := generator.Read(buffer)
	//   if err != nil {
	//       // handle error
	//   }
	//   fmt.Printf("Read %d random bytes\n", n)
	Read(b []byte) (n int, err error)
}

Interface defines the contract for generating Nano IDs.

Implementations of this interface provide methods to create new IDs and to read random data, supporting both ID generation and direct random byte access.

var (
	// Generator is a global, shared instance of a Nano ID generator. It is safe for concurrent use.
	Generator Interface

	// RandReader is the default random number generator used for generating IDs.
	RandReader = prng.Reader
)

func NewGenerator added in v1.10.0

func NewGenerator(options ...Option) (Interface, error)

NewGenerator creates a new Interface with buffer pooling enabled. It accepts variadic Option parameters to configure the Interface's behavior. The function initializes the configuration with default values, applies any provided options, validates the configuration, constructs the runtime configuration, initializes buffer pools, and returns a configured Interface or an error if the configuration is invalid.

Parameters:

  • options ...Option: A variadic list of Option functions to customize the Interface's configuration.

Returns:

  • Interface: An instance of the Interface interface configured with the specified options.
  • error: An error object if the Interface could not be created due to invalid configuration.

Error Conditions:

  • ErrInvalidLength: Returned if the provided LengthHint is less than 1.
  • ErrNilRandReader: Returned if the provided RandReader is nil.
  • ErrInvalidAlphabet: Returned if the alphabet is invalid or contains invalid UTF-8 characters.
  • ErrNonUTF8Alphabet: Returned if the alphabet contains non-UTF-8 characters.
  • ErrDuplicateCharacters: Returned if the alphabet contains duplicate characters.

type Option added in v1.10.0

type Option func(*ConfigOptions)

Option defines a function type for configuring the Interface. It allows for flexible and extensible configuration by applying various settings to the ConfigOptions during Interface initialization.

func WithAlphabet added in v1.10.0

func WithAlphabet(alphabet string) Option

WithAlphabet sets a custom alphabet for the Interface. The provided alphabet string defines the set of characters that will be used to generate Nano IDs. This allows users to customize the character set according to their specific requirements, such as using only alphanumeric characters, including symbols, or supporting non-ASCII characters.

Parameters:

  • alphabet string: A string representing the desired set of characters for ID generation.

Returns:

  • Option: A configuration option that applies the custom alphabet to ConfigOptions.

Usage:

generator, err := nanoid.NewGenerator(nanoid.WithAlphabet("abcdef123456"))

func WithLengthHint added in v1.12.0

func WithLengthHint(hint uint16) Option

WithLengthHint sets the hint of the intended length of the IDs to be generated. Providing a length hint allows the Interface to optimize internal configurations, such as buffer sizes and scaling factors, based on the expected ID length. This can enhance performance and efficiency, especially when generating a large number of IDs with similar lengths.

Parameters:

  • hint uint16: A non-zero unsigned integer representing the anticipated length of the Nano IDs.

Returns:

  • Option: A configuration option that applies the length hint to ConfigOptions.

Usage Example:

generator, err := nanoid.NewGenerator(nanoid.WithLengthHint(21))

func WithRandReader added in v1.10.0

func WithRandReader(reader io.Reader) Option

WithRandReader sets a custom random reader for the Interface. By default, the Interface uses a cryptographically secure random number generator (e.g., crypto/rand.Reader). However, in some cases, users might want to provide their own source of randomness, such as for testing purposes or to integrate with a different entropy source.

Parameters:

  • reader io.Reader: An implementation of io.Reader that supplies random data.

Returns:

  • Option: A configuration option that applies the custom random reader to ConfigOptions.

Usage Example:

 customReader := myCustomRandomReader()
 generator, err := nanoid.NewGenerator(
	nanoid.WithRandReader(customReader))

Directories

Path Synopsis
x

Jump to

Keyboard shortcuts

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