Last update: 2025-12-10
Generating (Human-Friendly) IDs in Go
Goals:
- Use a charset made of non-graphically confusable characters
- Use base-16 text encoding
- Be human-friendly
Default charset (16 characters): "2346789CHJKPTVXY".
package huid
import (
"crypto/rand"
"errors"
"fmt"
"io"
)
const Charset = "2346789CHJKPTVXY"
var (
ErrBadCharset = errors.New("huid: bad charset")
ErrReadPRNG = errors.New("huid: read from PRNG")
)
func init() {
if len(Charset) != 16 {
panic(ErrBadCharset)
}
}
// Generates a human-friendly ID using that only contains "safe" non-confusable characters
// and no vowels (to avoid generating human words).
// The character set is made from 16 alpha-numeric visually distinct ASCII characters.
// NB: One byte of entropy (N) will result in 2 characters of textual output (2N).
func New(n int) (id string) {
b := make([]byte, n)
_, err := io.ReadFull(rand.Reader, b)
if err != nil {
panic(fmt.Errorf("%w: %w", ErrReadPRNG, err))
}
for _, v := range b {
id += string(Charset[(v&0xF0)>>4])
id += string(Charset[(v&0x0F)>>0])
}
return id
}
NB: Since base-16 encoding is used, one BYTE (not bits) of entropy
results in two output BYTES in the New function below.