mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 12:52:28 +08:00
Merge branch 'v2' of github.com:duke-git/lancet into v2
This commit is contained in:
@@ -10,7 +10,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -27,7 +27,14 @@ const (
|
|||||||
AllChars = Numeral + LowwerLetters + UpperLetters + SymbolChars
|
AllChars = Numeral + LowwerLetters + UpperLetters + SymbolChars
|
||||||
)
|
)
|
||||||
|
|
||||||
var rn = rand.NewSource(time.Now().UnixNano())
|
// var rn = rand.NewSource(time.Now().UnixNano())
|
||||||
|
|
||||||
|
// 每个 goroutine 独立的 rand.Rand,避免并发问题
|
||||||
|
var randPool = sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
@@ -286,10 +293,9 @@ func nearestPowerOfTwo(cap int) int {
|
|||||||
|
|
||||||
// random generate a random string based on given string range.
|
// random generate a random string based on given string range.
|
||||||
func random(s string, length int) string {
|
func random(s string, length int) string {
|
||||||
// 确保随机数生成器的种子是动态的
|
// 从 pool 中获取 rand.Rand(替代全局 rand)
|
||||||
pid := os.Getpid()
|
rn := randPool.Get().(*rand.Rand)
|
||||||
timestamp := time.Now().UnixNano()
|
defer randPool.Put(rn)
|
||||||
rand.Seed(int64(pid) + timestamp)
|
|
||||||
|
|
||||||
// 仿照strings.Builder
|
// 仿照strings.Builder
|
||||||
// 创建一个长度为 length 的字节切片
|
// 创建一个长度为 length 的字节切片
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
@@ -376,3 +377,31 @@ func TestRandNumberOfLength(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestRandNumberOfLength")
|
assert := internal.NewAssert(t, "TestRandNumberOfLength")
|
||||||
assert.Equal(6, len(strconv.Itoa(randi)))
|
assert.Equal(6, len(strconv.Itoa(randi)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestRandStringConcurrent verifies RandString is safe under high concurrency.
|
||||||
|
// Before the fix, this test may panic or trigger data races.
|
||||||
|
// After the fix, it should always pass.
|
||||||
|
func TestRandStringConcurrent(t *testing.T) {
|
||||||
|
const (
|
||||||
|
goroutines = 100
|
||||||
|
iterations = 1000
|
||||||
|
length = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(goroutines)
|
||||||
|
|
||||||
|
for g := 0; g < goroutines; g++ {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for i := 0; i < iterations; i++ {
|
||||||
|
s := RandString(length)
|
||||||
|
if len(s) != length {
|
||||||
|
t.Fatalf("unexpected string length: got %d, want %d", len(s), length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user