Last active
May 17, 2021 21:56
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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