Skip to content

Instantly share code, notes, and snippets.

@xkisu
Last active May 17, 2021 21:56
Show Gist options
  • Save xkisu/b96ffe5dadcd8d034dbd55db2b78d432 to your computer and use it in GitHub Desktop.
Save xkisu/b96ffe5dadcd8d034dbd55db2b78d432 to your computer and use it in GitHub Desktop.
A short unique ID generation method based on the ID generation used in Hashicorp Boundary and Vault
package shortid
import (
"crypto/rand"
"fmt"
"io"
)
// Base58 contains the encoding charset for base58 encoding.
//
// Base58 was invented by Satoshi Nakamoto while creating
// Bitcoin. Base58 is ideal for encoding ID's that people will
// read or need to type out because the character set excludes
// characters the look similar and could be commonly mistaken.
const Base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
// Base58Len contains the length of the base58 encoding charset.
const Base58Len = byte(len(Base58))
// NewWithLength returns a new short id
func NewWithLength (length int) string {
output := make([]byte, 0, length)
// Request a bit more than length to reduce the chance
// of needing more than one batch of random bytes
batchSize := length + length/4
for {
buf := make([]byte, batchSize)
if _, err := io.ReadFull(rand.Reader, buf); err != nil {
panic(fmt.Errorf("failed to read random bytes: %v", err))
}
for _, b := range buf {
// Avoid bias by using a value range that's a multiple of 62
if b < (Base58Len * 4) {
output = append(output, Base58[b%Base58Len])
if len(output) == length {
return string(output)
}
}
}
}
return ""
}
// New returns a new short id that's 10 characters long
func New () string {
return NewWithLength(10)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment