6

GitHub - jaevor/go-nanoid: Nano ID in Go -- very fast and efficient unique ID ge...

 1 year ago
source link: https://github.com/jaevor/go-nanoid
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

go-nanoid

This module is a Go implementation of nanoid.

Features of the nanoid spec are:

  • URL friendly
  • Use of hardware random generator
  • Uses a bigger alphabet than UUID, so a similar number of random bits are packed in just 21 chars instead of 36 (like UUID)
  • Much, much faster than UUID (v4)

Features of this specific implementation are:

  • Fastest and most performant implementation of Nano ID around (benchmarks)
  • Prefetches random bytes in advance
  • Uses optimal memory
  • No production dependencies

Security

See comparison of Nano ID and UUID (V4):

"Nano ID is quite comparable to UUID v4 (random-based). It has a similar number of random bits in the ID (126 in Nano ID and 122 in UUID), so it has a similar collision probability -- for there to be a one in a billion chance of duplication, 103 trillion version 4 IDs must be generated"

And NanoID collision calculator:

If 1,000,000 Nano IDs (using nanoid.Standard(21)) were generated each second, it would require ~41 thousand years in order to have a 1% probability of a collision

In other words, with 21 characters, the total number of possible unique IDs would be 21^64, which is ~four septenvigintillion (4 followed by 84 zeros) -- a figure larger than the number of atoms that exist in the universe, apparently

Read more here

Example

import (
	"log"
	"math/rand"
	"time"
	"github.com/jaevor/go-nanoid"
)

func main() {
  createNanoid, err := nanoid.Standard(21)
  if err != nil {
    panic(err)
  }

  id1 := createNanoid()
  log.Printf("ID 1: %s", id1) // Sk4rC4fjsRm-LS1gtbL1y

  // [!] Remember to seed. 
  rand.Seed(time.Now().Unix())

  createNonSecureNanoid, err := nanoid.StandardNonSecure(21)
  if err != nil {
    panic(err)
  }

  id2 := createNonSecureNanoid()
  log.Printf("ID 2: %s", id2) // japKZqwnQvllgUQ8lwgkP

  createCustomNanoid, err := nanoid.Custom("0123456789", 12)
  if err != nil {
    panic(err)
  }

  id3 := createCustomNanoid()
  log.Printf("ID 3: %s", id3) // 462855288020
}

Notes

Might remove all non-secure Nano ID generators in the future. The benefit of the trade-off between using them and not the secure ones should be speed, but I can't figure out how to get PRNG fast

Remember to rand.Seed(...) before using the non-secure generators

In terms of speed & efficiency, it is probably always better to use Standard Nano ID than any Custom

Benchmarks

All benchmarks & tests can be found in nanoid_test.go.

These are all benchmarks of the Standard Nano ID generator

# of characters & # of IDs benchmark screenshot
8, ~21,800,000
21, ~16,400,000
36, ~11,500,000
255, ~2,500,000

Credits & references

License

MIT License


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK