feat: Randomizer
This commit is contained in:
99
rand/randomizer.go
Normal file
99
rand/randomizer.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
cryptoRand "crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
|
"golang.org/x/exp/rand"
|
||||||
|
"hash/maphash"
|
||||||
|
mathRand "math/rand"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SeedType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
UnixNanoSeed SeedType = "UnixNano"
|
||||||
|
MapHashSeed SeedType = "MapHash"
|
||||||
|
CryptoRandSeed SeedType = "CryptoRand"
|
||||||
|
RandomStringSeed SeedType = "RandomString"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Randomizer struct {
|
||||||
|
seedType SeedType
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRandomizer(seedType SeedType) *Randomizer {
|
||||||
|
return &Randomizer{
|
||||||
|
seedType: seedType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Randomizer) UnixNano() int64 {
|
||||||
|
// 获取当前时间戳
|
||||||
|
timestamp := time.Now().UnixNano()
|
||||||
|
|
||||||
|
// 生成一个随机数
|
||||||
|
var randomBytes [8]byte
|
||||||
|
_, err := rand.Read(randomBytes[:])
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to generate random bytes")
|
||||||
|
}
|
||||||
|
randomPart := int64(binary.LittleEndian.Uint64(randomBytes[:]))
|
||||||
|
|
||||||
|
// 获取 Goroutine ID(或其他唯一标识)
|
||||||
|
goroutineID := int64(runtime.NumGoroutine())
|
||||||
|
|
||||||
|
// 结合时间戳、随机数和 Goroutine ID
|
||||||
|
seed := timestamp ^ randomPart ^ goroutineID
|
||||||
|
|
||||||
|
return seed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Randomizer) MapHash() int64 {
|
||||||
|
return int64(new(maphash.Hash).Sum64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Randomizer) CryptoRand() int64 {
|
||||||
|
var b [8]byte
|
||||||
|
_, err := cryptoRand.Read(b[:])
|
||||||
|
if err != nil {
|
||||||
|
panic("cannot seed math/rand package with cryptographically secure random number generator")
|
||||||
|
}
|
||||||
|
seed := int64(binary.LittleEndian.Uint64(b[:]))
|
||||||
|
return seed
|
||||||
|
}
|
||||||
|
|
||||||
|
var Alpha = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
|
||||||
|
|
||||||
|
func (r *Randomizer) RandomString() int64 {
|
||||||
|
const size = 8
|
||||||
|
buf := make([]byte, size)
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
buf[i] = Alpha[mathRand.Intn(len(Alpha))]
|
||||||
|
}
|
||||||
|
seed := int64(binary.LittleEndian.Uint64(buf[:]))
|
||||||
|
|
||||||
|
return seed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Randomizer) Seed() int64 {
|
||||||
|
switch r.seedType {
|
||||||
|
default:
|
||||||
|
fallthrough
|
||||||
|
case UnixNanoSeed:
|
||||||
|
return r.UnixNano()
|
||||||
|
case MapHashSeed:
|
||||||
|
return r.MapHash()
|
||||||
|
case CryptoRandSeed:
|
||||||
|
return r.CryptoRand()
|
||||||
|
case RandomStringSeed:
|
||||||
|
return r.RandomString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seed generates a seed based on the specified SeedType.
|
||||||
|
func Seed(seedType SeedType) int64 {
|
||||||
|
randomizer := NewRandomizer(seedType)
|
||||||
|
return randomizer.Seed()
|
||||||
|
}
|
||||||
80
rand/randomizer_test.go
Normal file
80
rand/randomizer_test.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUnixNano(t *testing.T) {
|
||||||
|
randomizer := NewRandomizer(UnixNanoSeed)
|
||||||
|
|
||||||
|
var seeds = make(map[int64]bool)
|
||||||
|
for i := 0; i < 100000; i++ {
|
||||||
|
seed := randomizer.Seed()
|
||||||
|
seeds[seed] = true
|
||||||
|
}
|
||||||
|
fmt.Println("UnixNano Seed", len(seeds))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapHash(t *testing.T) {
|
||||||
|
randomizer := NewRandomizer(MapHashSeed)
|
||||||
|
|
||||||
|
var seeds = make(map[int64]bool)
|
||||||
|
for i := 0; i < 100000; i++ {
|
||||||
|
seed := randomizer.Seed()
|
||||||
|
seeds[seed] = true
|
||||||
|
}
|
||||||
|
fmt.Println("MapHash Seed", len(seeds))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCryptoRand(t *testing.T) {
|
||||||
|
randomizer := NewRandomizer(CryptoRandSeed)
|
||||||
|
|
||||||
|
var seeds = make(map[int64]bool)
|
||||||
|
for i := 0; i < 100000; i++ {
|
||||||
|
seed := randomizer.Seed()
|
||||||
|
seeds[seed] = true
|
||||||
|
}
|
||||||
|
fmt.Println("CryptoRand Seed", len(seeds))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandomString(t *testing.T) {
|
||||||
|
randomizer := NewRandomizer(RandomStringSeed)
|
||||||
|
|
||||||
|
var seeds = make(map[int64]bool)
|
||||||
|
for i := 0; i < 100000; i++ {
|
||||||
|
seed := randomizer.Seed()
|
||||||
|
seeds[seed] = true
|
||||||
|
}
|
||||||
|
fmt.Println("RandomString Seed", len(seeds))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSeed(t *testing.T) {
|
||||||
|
var seeds = make(map[int64]bool)
|
||||||
|
for i := 0; i < 100000; i++ {
|
||||||
|
seed := Seed(UnixNanoSeed)
|
||||||
|
seeds[seed] = true
|
||||||
|
}
|
||||||
|
fmt.Println("UnixNano Seed", len(seeds))
|
||||||
|
|
||||||
|
seeds = make(map[int64]bool)
|
||||||
|
for i := 0; i < 100000; i++ {
|
||||||
|
seed := Seed(MapHashSeed)
|
||||||
|
seeds[seed] = true
|
||||||
|
}
|
||||||
|
fmt.Println("MapHash Seed", len(seeds))
|
||||||
|
|
||||||
|
seeds = make(map[int64]bool)
|
||||||
|
for i := 0; i < 100000; i++ {
|
||||||
|
seed := Seed(CryptoRandSeed)
|
||||||
|
seeds[seed] = true
|
||||||
|
}
|
||||||
|
fmt.Println("CryptoRand Seed", len(seeds))
|
||||||
|
|
||||||
|
seeds = make(map[int64]bool)
|
||||||
|
for i := 0; i < 100000; i++ {
|
||||||
|
seed := Seed(RandomStringSeed)
|
||||||
|
seeds[seed] = true
|
||||||
|
}
|
||||||
|
fmt.Println("RandomString Seed", len(seeds))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user