github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/random.go (about) 1 package util 2 3 import ( 4 "crypto/rand" 5 "encoding/hex" 6 "errors" 7 "math" 8 ) 9 10 const ( 11 letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 12 letterIdxBits = 6 // 6 bits to represent a letter index 13 letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits 14 letterIdxMax = 31 / letterIdxBits // # of letter indices fitting in 31 bits 15 ) 16 17 var ( 18 // Rand goroutine-safe, use Rand.xxx instead of rand.xxx 19 Rand = NewRand() 20 Seed = FastRand() 21 ) 22 23 // RandInt (>=)min - (<)max 24 func RandInt(min, max int) int { 25 if max == min { 26 return min 27 } 28 if max < min { 29 min, max = max, min 30 } 31 return FastIntn(max-min) + min 32 } 33 34 // RandUint32 (>=)min - (<)max 35 func RandUint32(min, max uint32) uint32 { 36 if max == min { 37 return min 38 } 39 if max < min { 40 min, max = max, min 41 } 42 return FastRandn(max-min) + min 43 } 44 45 // FastIntn this is similar to rand.Intn, but faster. 46 // A non-negative pseudo-random number in the half-open interval [0,n). 47 // Return 0 if n <= 0. 48 func FastIntn(n int) int { 49 if n <= 0 { 50 return 0 51 } 52 if n <= math.MaxUint32 { 53 return int(FastRandn(uint32(n))) 54 } 55 return int(Rand.Int63n(int64(n))) 56 } 57 58 // RandString a random string, which may contain uppercase letters, lowercase letters and numbers. 59 // Ref: stackoverflow.icza 60 func RandString(n int) string { 61 return string(FastRandBytes(n)) 62 } 63 64 // RandHex a random string containing only the following characters: 0123456789abcdef 65 func RandHex(nHalf int) string { 66 return hex.EncodeToString(FastRandBytes(nHalf)) 67 } 68 69 // RandBytes returns n random bytes 70 func RandBytes(n int) ([]byte, error) { 71 if n < 1 { 72 return nil, errors.New("invalid argument: n must be greater than zero") 73 } 74 75 b := make([]byte, n) 76 if _, err := rand.Read(b); err != nil { 77 return nil, err 78 } 79 80 return b, nil 81 } 82 83 // FastRandBytes random bytes, but faster. 84 func FastRandBytes(n int) []byte { 85 if n < 1 { 86 return nil 87 } 88 b := make([]byte, n) 89 for i, cache, remain := n-1, FastRand(), letterIdxMax; i >= 0; { 90 if remain == 0 { 91 cache, remain = FastRand(), letterIdxMax 92 } 93 if idx := int(cache & letterIdxMask); idx < len(letterBytes) { 94 b[i], i = letterBytes[idx], i-1 95 } 96 cache >>= letterIdxBits 97 remain-- 98 } 99 return b 100 }