mirror of
https://github.com/samber/lo.git
synced 2025-09-26 20:11:13 +08:00
refactor:refactor RandomString function (#524)
* refactor:refactor RandomString function * feat:Upgrade math/rand to math/rand/v2 * Update string.go Co-authored-by: ccoVeille <3875889+ccoVeille@users.noreply.github.com> * feat: improve comments for RandomString function * Update string.go Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr> * feat:Upgrade math/rand/v2 to github.com/samber/lo/internal/rand * Update string.go * Update ordered_go118.go --------- Co-authored-by: zhuhebin <zhuhebin@fengtaisec.com> Co-authored-by: ccoVeille <3875889+ccoVeille@users.noreply.github.com> Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
This commit is contained in:
@@ -12,3 +12,15 @@ func IntN(n int) int {
|
||||
// bearer:disable go_gosec_crypto_weak_random
|
||||
return rand.Intn(n)
|
||||
}
|
||||
|
||||
func Int64() int64 {
|
||||
// bearer:disable go_gosec_crypto_weak_random
|
||||
n := rand.Int63()
|
||||
|
||||
// bearer:disable go_gosec_crypto_weak_random
|
||||
if rand.Intn(2) == 0 {
|
||||
return -n
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
@@ -11,3 +11,7 @@ func Shuffle(n int, swap func(i, j int)) {
|
||||
func IntN(n int) int {
|
||||
return rand.IntN(n)
|
||||
}
|
||||
|
||||
func Int64() int64 {
|
||||
return rand.Int64()
|
||||
}
|
||||
|
56
string.go
56
string.go
@@ -1,13 +1,13 @@
|
||||
package lo
|
||||
|
||||
import (
|
||||
"github.com/samber/lo/internal/rand"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/samber/lo/internal/rand"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
@@ -25,6 +25,7 @@ var (
|
||||
splitWordReg = regexp.MustCompile(`([a-z])([A-Z0-9])|([a-zA-Z])([0-9])|([0-9])([a-zA-Z])|([A-Z])([A-Z])([a-z])`)
|
||||
// bearer:disable go_lang_permissive_regex_validation
|
||||
splitNumberLetterReg = regexp.MustCompile(`([0-9])([a-zA-Z])`)
|
||||
maximumCapacity = math.MaxInt>>1 + 1
|
||||
)
|
||||
|
||||
// RandomString return a random string.
|
||||
@@ -37,12 +38,53 @@ func RandomString(size int, charset []rune) string {
|
||||
panic("lo.RandomString: Charset parameter must not be empty")
|
||||
}
|
||||
|
||||
b := make([]rune, size)
|
||||
possibleCharactersCount := len(charset)
|
||||
for i := range b {
|
||||
b[i] = charset[rand.IntN(possibleCharactersCount)]
|
||||
// see https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
|
||||
sb := strings.Builder{}
|
||||
sb.Grow(size)
|
||||
// Calculate the number of bits required to represent the charset,
|
||||
// e.g., for 62 characters, it would need 6 bits (since 62 -> 64 = 2^6)
|
||||
letterIdBits := int(math.Log2(float64(nearestPowerOfTwo(len(charset)))))
|
||||
// Determine the corresponding bitmask,
|
||||
// e.g., for 62 characters, the bitmask would be 111111.
|
||||
var letterIdMask int64 = 1<<letterIdBits - 1
|
||||
// Available count, since rand.Int64() returns a non-negative number, the first bit is fixed, so there are 63 random bits
|
||||
// e.g., for 62 characters, this value is 10 (63 / 6).
|
||||
letterIdMax := 63 / letterIdBits
|
||||
// Generate the random string in a loop.
|
||||
for i, cache, remain := size-1, rand.Int64(), letterIdMax; i >= 0; {
|
||||
// Regenerate the random number if all available bits have been used
|
||||
if remain == 0 {
|
||||
cache, remain = rand.Int64(), letterIdMax
|
||||
}
|
||||
// Select a character from the charset
|
||||
if idx := int(cache & letterIdMask); idx < len(charset) {
|
||||
sb.WriteRune(charset[idx])
|
||||
i--
|
||||
}
|
||||
// Shift the bits to the right to prepare for the next character selection,
|
||||
// e.g., for 62 characters, shift by 6 bits.
|
||||
cache >>= letterIdBits
|
||||
// Decrease the remaining number of uses for the current random number.
|
||||
remain--
|
||||
}
|
||||
return string(b)
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// nearestPowerOfTwo returns the nearest power of two.
|
||||
func nearestPowerOfTwo(cap int) int {
|
||||
n := cap - 1
|
||||
n |= n >> 1
|
||||
n |= n >> 2
|
||||
n |= n >> 4
|
||||
n |= n >> 8
|
||||
n |= n >> 16
|
||||
if n < 0 {
|
||||
return 1
|
||||
}
|
||||
if n >= maximumCapacity {
|
||||
return maximumCapacity
|
||||
}
|
||||
return n + 1
|
||||
}
|
||||
|
||||
// Substring return part of a string.
|
||||
|
Reference in New Issue
Block a user