Files
xlgo-core/utils/random.go
T
杭州明婳科技 2dfcbbbb22 init
2026-04-30 23:26:14 +08:00

104 lines
2.4 KiB
Go

package utils
import (
"math/rand"
"sync"
"time"
)
var (
randPool = sync.Pool{
New: func() any {
return rand.New(rand.NewSource(time.Now().UnixNano()))
},
}
)
const (
letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
digitBytes = "0123456789"
letterIdxBits = 6 // 6 bits to represent a letter index (0-63)
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
// RandString 生成指定长度的随机字符串(字母+数字)
// 评分: ⭐⭐⭐⭐⭐
// 理由: 使用 sync.Pool 复用 rand.Source,性能优秀;位运算优化高效
func RandString(n int) string {
if n <= 0 {
return ""
}
b := make([]byte, n)
r := randPool.Get().(*rand.Rand)
defer randPool.Put(r)
for i, cache, remain := n-1, r.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = r.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
b[i] = letterBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
}
return string(b)
}
// RandDigit 生成指定长度的随机数字字符串
// 评分: ⭐⭐⭐⭐⭐
// 理由: 同 RandString,适用于验证码、订单号等场景
func RandDigit(n int) string {
if n <= 0 {
return ""
}
b := make([]byte, n)
r := randPool.Get().(*rand.Rand)
defer randPool.Put(r)
for i, cache, remain := n-1, r.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = r.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(digitBytes) {
b[i] = digitBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
}
return string(b)
}
// RandInt 返回 [min, max) 范围内的随机整数
// 评分: ⭐⭐⭐⭐
// 理由: 实用函数,自动处理 min > max 的情况
func RandInt(min, max int) int {
if min == max {
return min
}
if max < min {
min, max = max, min
}
r := randPool.Get().(*rand.Rand)
defer randPool.Put(r)
return min + r.Intn(max-min)
}
// RandInt64 返回 [min, max) 范围内的随机 int64
// 评分: ⭐⭐⭐⭐
// 理由: RandInt 的 int64 版本,适用于大范围随机数
func RandInt64(min, max int64) int64 {
if min == max {
return min
}
if max < min {
min, max = max, min
}
r := randPool.Get().(*rand.Rand)
defer randPool.Put(r)
return min + r.Int63n(max-min)
}