Last active
January 22, 2018 07:46
-
-
Save jinroh/7ec9e44db1e5f796ede6920f75862477 to your computer and use it in GitHub Desktop.
Generate random string in Go
This file contains hidden or 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
BenchmarkRandomStringA-4 2000000 702 ns/op | |
BenchmarkRandomStringB-4 10000000 120 ns/op | |
BenchmarkRandomStringC-4 20000000 115 ns/op | |
BenchmarkRandomStringD-4 10000000 121 ns/op |
This file contains hidden or 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
func RandomStringA(n int) string { | |
const letters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-" | |
b := make([]byte, n) | |
lenLetters := len(letters) | |
for i := 0; i < n; i++ { | |
b[i] = letters[rand.Intn(lenLetters)] | |
} | |
return string(b) | |
} | |
func RandomStringB(rng *rand.Rand, n int) string { | |
const letters = `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-` | |
b := make([]byte, ((n+9)/10)*10) | |
for i := 0; i < n; i += 10 { | |
rn := rng.Uint64() | |
b[i+0] = letters[(rn&0x0FC0000000000000)>>54] | |
b[i+1] = letters[(rn&0x003F000000000000)>>48] | |
b[i+2] = letters[(rn&0x0000FC0000000000)>>42] | |
b[i+3] = letters[(rn&0x000003F000000000)>>36] | |
b[i+4] = letters[(rn&0x0000000FC0000000)>>30] | |
b[i+5] = letters[(rn&0x000000003F000000)>>24] | |
b[i+6] = letters[(rn&0x0000000000FC0000)>>18] | |
b[i+7] = letters[(rn&0x000000000003F000)>>12] | |
b[i+8] = letters[(rn&0x0000000000000FC0)>>6] | |
b[i+9] = letters[(rn&0x000000000000003F)>>0] | |
} | |
return string(b[:n]) | |
} | |
func RandomStringC(rng *rand.Rand, n int) string { | |
// extract 10 letters — 60 bits of entropy — for each pseudo-random uint64 | |
const K = 10 | |
const L = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-" | |
b := make([]byte, ((n+K-1)/K)*K) | |
for i := 0; i < n; i += K { | |
rn := rng.Uint64() | |
for j := 0; j < K; j++ { | |
b[i+j] = L[rn&0x3F] | |
rn >>= 6 | |
} | |
} | |
return string(b[:n]) | |
} | |
func RandomStringD(rng *rand.Rand, n int) string { | |
const letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-" | |
const ( | |
letterIdxBits = 6 // 6 bits to represent a letter index | |
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits | |
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits | |
) | |
b := make([]byte, n) | |
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters! | |
for i, cache, remain := n-1, rng.Int63(), letterIdxMax; i >= 0; { | |
if remain == 0 { | |
cache, remain = rng.Int63(), letterIdxMax | |
} | |
idx := int(cache & letterIdxMask) | |
b[i] = letterBytes[idx] | |
i-- | |
cache >>= letterIdxBits | |
remain-- | |
} | |
return string(b) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment