Go math/rand/v2 包详解
概述
math/rand/v2 包是 Go 1.22 引入的新版伪随机数生成器包。相比旧的 math/rand 包,v2 版本提供了更好的 API 设计、新的随机源实现(PCG 和 ChaCha8)、以及更多功能。适用于模拟、测试等非安全敏感场景。
重要说明:
- ⚠️ 不应用于安全敏感场景(如密码、令牌)
- ✓ Go 1.22+ 引入的新版本 API
- ✓ 提供 PCG 和 ChaCha8 两种随机源
- ✓ 包级别函数是线程安全的
- ✓
Rand类型不是线程安全的,需要加锁 - ✓ 自动种子化,无需手动调用 Seed
包导入
import "math/rand/v2"
基本使用
1. 生成随机整数
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 生成随机整数
fmt.Printf("随机 int: %d\n", rand.Int())
fmt.Printf("随机 int64: %d\n", rand.Int64())
fmt.Printf("随机 int32: %d\n", rand.Int32())
// 生成范围内的随机数
fmt.Printf("0-99: %d\n", rand.IntN(100))
fmt.Printf("0-9: %d\n", rand.Int32N(10))
fmt.Printf("0-999: %d\n", rand.Int64N(1000))
}
2. 生成随机浮点数
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 生成随机浮点数
fmt.Printf("float64: %f\n", rand.Float64())
fmt.Printf("float32: %f\n", rand.Float32())
}
3. 使用 PCG 随机源
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 创建 PCG 随机源
pcg := rand.NewPCG(42, 123)
r := rand.New(pcg)
// 使用 Rand 对象
fmt.Printf("随机数 1: %d\n", r.IntN(100))
fmt.Printf("随机数 2: %d\n", r.IntN(100))
fmt.Printf("随机数 3: %d\n", r.IntN(100))
}
一、包级别函数
ExpFloat64
定义:
func ExpFloat64() float64
说明:
- 功能:返回指数分布的 float64
- 返回值:
float64- 范围 (0, +MaxFloat64] - 分布:速率参数 λ=1,均值=1
- 用途:模拟事件间隔时间
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 生成指数分布随机数
for i := 0; i < 5; i++ {
fmt.Printf("%.4f\n", rand.ExpFloat64())
}
// 调整速率参数
rate := 2.0
sample := rand.ExpFloat64() / rate
fmt.Printf("速率=%.2f 的样本:%.4f\n", rate, sample)
}
Float32
定义:
func Float32() float32
说明:
- 功能:返回 [0.0, 1.0) 范围内的随机 float32
- 返回值:
float32
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 生成 5 个随机 float32
for i := 0; i < 5; i++ {
fmt.Printf("%.4f\n", rand.Float32())
}
}
Float64
定义:
func Float64() float64
说明:
- 功能:返回 [0.0, 1.0) 范围内的随机 float64
- 返回值:
float64
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 生成 5 个随机 float64
for i := 0; i < 5; i++ {
fmt.Printf("%.6f\n", rand.Float64())
}
}
Int
定义:
func Int() int
说明:
- 功能:返回非负随机整数
- 返回值:
int- 范围 [0, MaxInt]
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 生成 5 个随机整数
for i := 0; i < 5; i++ {
fmt.Printf("%d\n", rand.Int())
}
}
Int32
定义:
func Int32() int32
说明:
- 功能:返回非负 32 位随机整数
- 返回值:
int32- 范围 [0, 2^32-1] - 注意:v2 版本使用 Int32 替代了 v1 的 Int31
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
fmt.Printf("随机 int32: %d\n", rand.Int32())
fmt.Printf("最大值:2^32-1 = %d\n", int32(^uint32(0)>>1))
}
Int32N
定义:
func Int32N(n int32) int32
说明:
- 功能:返回 [0, n) 范围内的随机 int32
- 参数:
n- 上界(必须 > 0) - 返回值:
int32 - 注意:n <= 0 时会 panic
- 变化:v2 版本使用 Int32N 替代了 v1 的 Int31n
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 模拟骰子
fmt.Printf("骰子:%d\n", rand.Int32N(6)+1)
// 生成 10 个 0-99 的随机数
for i := 0; i < 10; i++ {
fmt.Printf("%d ", rand.Int32N(100))
}
}
Int64
定义:
func Int64() int64
说明:
- 功能:返回非负 64 位随机整数
- 返回值:
int64- 范围 [0, 2^63-1] - 注意:v2 版本使用 Int64 替代了 v1 的 Int63
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
fmt.Printf("随机 int64: %d\n", rand.Int64())
}
Int64N
定义:
func Int64N(n int64) int64
说明:
- 功能:返回 [0, n) 范围内的随机 int64
- 参数:
n- 上界(必须 > 0) - 返回值:
int64 - 注意:n <= 0 时会 panic
- 变化:v2 版本使用 Int64N 替代了 v1 的 Int63n
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 大范围随机数
n := rand.Int64N(1000000)
fmt.Printf("0-999999: %d\n", n)
}
IntN
定义:
func IntN(n int) int
说明:
- 功能:返回 [0, n) 范围内的随机 int
- 参数:
n- 上界(必须 > 0) - 返回值:
int - 注意:n <= 0 时会 panic
- 变化:v2 版本使用 IntN 替代了 v1 的 Intn
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 模拟骰子
dice := rand.IntN(6) + 1
fmt.Printf("骰子点数:%d\n", dice)
// 随机数组索引
items := []string{"苹果", "香蕉", "橙子", "葡萄"}
randomItem := items[rand.IntN(len(items))]
fmt.Printf("随机选择:%s\n", randomItem)
}
N
定义:
func N[Int intType](n Int) Int
说明:
- 功能:泛型版本的范围随机数生成
- 类型参数:
Int- 整数类型(int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64) - 参数:
n- 上界(必须 > 0) - 返回值:
Int- [0, n) 范围内的随机数 - 特点:Go 1.22+ 泛型支持
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 使用泛型函数
fmt.Printf("int8: %d\n", rand.N[int8](100))
fmt.Printf("int16: %d\n", rand.N[int16](1000))
fmt.Printf("uint32: %d\n", rand.N[uint32](10000))
fmt.Printf("uint64: %d\n", rand.N[uint64](1000000))
}
NormFloat64
定义:
func NormFloat64() float64
说明:
- 功能:返回标准正态分布的 float64
- 返回值:
float64- 范围 [-MaxFloat64, +MaxFloat64] - 分布:均值=0,标准差=1
- 用途:模拟自然现象、蒙特卡洛模拟
示例:
package main
import (
"fmt"
"math"
"math/rand/v2"
)
func main() {
// 生成标准正态分布样本
fmt.Println("标准正态分布 (μ=0, σ=1):")
for i := 0; i < 5; i++ {
fmt.Printf("%.4f\n", rand.NormFloat64())
}
// 调整均值和标准差
mean := 100.0
stddev := 15.0
sample := rand.NormFloat64()*stddev + mean
fmt.Printf("\n调整后 (μ=%.0f, σ=%.0f): %.4f\n", mean, stddev, sample)
}
Perm
定义:
func Perm(n int) []int
说明:
- 功能:返回 [0, n) 的随机排列
- 参数:
n- 排列长度 - 返回值:
[]int- 随机排列的切片
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 生成 0-9 的随机排列
perm := rand.Perm(10)
fmt.Printf("随机排列:%v\n", perm)
// 洗牌算法
cards := []string{"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
indices := rand.Perm(len(cards))
fmt.Print("洗牌后:")
for _, idx := range indices {
fmt.Printf("%s ", cards[idx])
}
}
Shuffle
定义:
func Shuffle(n int, swap func(i, j int))
说明:
- 功能:随机打乱序列
- 参数:
n- 序列长度swap- 交换函数
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 打乱切片
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Printf("打乱前:%v\n", numbers)
rand.Shuffle(len(numbers), func(i, j int) {
numbers[i], numbers[j] = numbers[j], numbers[i]
})
fmt.Printf("打乱后:%v\n", numbers)
}
Uint
定义:
func Uint() uint
说明:
- 功能:返回随机无符号整数
- 返回值:
uint
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
fmt.Printf("随机 uint: %d\n", rand.Uint())
}
Uint32
定义:
func Uint32() uint32
说明:
- 功能:返回随机 32 位无符号整数
- 返回值:
uint32- 范围 [0, 2^32-1] - 变化:v2 版本新增函数
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
fmt.Printf("随机 uint32: %d\n", rand.Uint32())
fmt.Printf("十六进制:0x%08X\n", rand.Uint32())
}
Uint32N
定义:
func Uint32N(n uint32) uint32
说明:
- 功能:返回 [0, n) 范围内的随机 uint32
- 参数:
n- 上界(必须 > 0) - 返回值:
uint32 - 注意:n <= 0 时会 panic
- 变化:v2 版本新增函数
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
fmt.Printf("0-999: %d\n", rand.Uint32N(1000))
}
Uint64
定义:
func Uint64() uint64
说明:
- 功能:返回随机 64 位无符号整数
- 返回值:
uint64- 范围 [0, 2^64-1] - 变化:v2 版本新增函数
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
fmt.Printf("随机 uint64: %d\n", rand.Uint64())
fmt.Printf("十六进制:0x%016X\n", rand.Uint64())
}
Uint64N
定义:
func Uint64N(n uint64) uint64
说明:
- 功能:返回 [0, n) 范围内的随机 uint64
- 参数:
n- 上界(必须 > 0) - 返回值:
uint64 - 注意:n <= 0 时会 panic
- 变化:v2 版本新增函数
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
fmt.Printf("0-999999: %d\n", rand.Uint64N(1000000))
}
UintN
定义:
func UintN(n uint) uint
说明:
- 功能:返回 [0, n) 范围内的随机 uint
- 参数:
n- 上界(必须 > 0) - 返回值:
uint - 注意:n <= 0 时会 panic
- 变化:v2 版本新增函数
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
fmt.Printf("0-99: %d\n", rand.UintN(100))
}
二、ChaCha8 类型
ChaCha8 结构体
定义:
type ChaCha8 struct {
// 包含未导出的字段
}
说明:
- 功能:ChaCha8 加密算法的随机数生成器
- 特点:
- 加密安全的随机源
- 需要 32 字节种子
- 支持二进制序列化
NewChaCha8
定义:
func NewChaCha8(seed [32]byte) *ChaCha8
说明:
- 功能:创建 ChaCha8 随机源
- 参数:
seed- 32 字节种子 - 返回值:
*ChaCha8
示例:
package main
import (
"crypto/rand"
"fmt"
"math/rand/v2"
)
func main() {
// 生成随机种子
var seed [32]byte
rand.Read(seed[:])
// 创建 ChaCha8 随机源
chacha := rand.NewChaCha8(seed)
r := rand.New(chacha)
// 使用
fmt.Printf("随机数:%d\n", r.IntN(100))
}
ChaCha8 方法
AppendBinary
定义:
func (c *ChaCha8) AppendBinary(b []byte) ([]byte, error)
说明:
- 功能:追加二进制编码
MarshalBinary
定义:
func (c *ChaCha8) MarshalBinary() ([]byte, error)
说明:
- 功能:二进制序列化
Read
定义:
func (c *ChaCha8) Read(p []byte) (n int, err error)
说明:
- 功能:生成随机字节
Seed
定义:
func (c *ChaCha8) Seed(seed [32]byte)
说明:
- 功能:重新设置种子
Uint64
定义:
func (c *ChaCha8) Uint64() uint64
说明:
- 功能:生成随机 uint64
UnmarshalBinary
定义:
func (c *ChaCha8) UnmarshalBinary(data []byte) error
说明:
- 功能:从二进制数据反序列化
三、PCG 类型
PCG 结构体
定义:
type PCG struct {
// 包含未导出的字段
}
说明:
- 功能:PCG (Permuted Congruential Generator) 随机数生成器
- 特点:
- 高质量的伪随机数生成器
- 需要两个 64 位种子
- 支持二进制序列化
NewPCG
定义:
func NewPCG(seed1, seed2 uint64) *PCG
说明:
- 功能:创建 PCG 随机源
- 参数:
seed1- 第一个种子seed2- 第二个种子
- 返回值:
*PCG
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 创建 PCG 随机源
pcg := rand.NewPCG(42, 123)
r := rand.New(pcg)
// 使用
fmt.Printf("随机数:%d\n", r.IntN(100))
fmt.Printf("随机数:%d\n", r.IntN(100))
}
PCG 方法
AppendBinary
定义:
func (p *PCG) AppendBinary(b []byte) ([]byte, error)
说明:
- 功能:追加二进制编码
MarshalBinary
定义:
func (p *PCG) MarshalBinary() ([]byte, error)
说明:
- 功能:二进制序列化
Seed
定义:
func (p *PCG) Seed(seed1, seed2 uint64)
说明:
- 功能:重新设置种子
Uint64
定义:
func (p *PCG) Uint64() uint64
说明:
- 功能:生成随机 uint64
UnmarshalBinary
定义:
func (p *PCG) UnmarshalBinary(data []byte) error
说明:
- 功能:从二进制数据反序列化
四、Rand 类型
Rand 结构体
定义:
type Rand struct {
// 包含未导出的字段
}
说明:
- 功能:随机数生成器
- 特点:
- 不是线程安全的
- 可自定义 Source
- 可重现随机序列
New
定义:
func New(src Source) *Rand
说明:
- 功能:创建新的 Rand 实例
- 参数:
src- 随机源 - 返回值:
*Rand
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 创建 PCG 随机源
pcg := rand.NewPCG(12345, 67890)
r := rand.New(pcg)
// 使用自定义随机源
fmt.Printf("IntN(100): %d\n", r.IntN(100))
fmt.Printf("Float64: %f\n", r.Float64())
fmt.Printf("Perm(5): %v\n", r.Perm(5))
}
Rand 方法
Rand 类型的方法与包级别函数基本相同,包括:
- ExpFloat64、Float32、Float64
- Int、Int32、Int32N、Int64、Int64N、IntN
- NormFloat64、Perm、Shuffle
- Uint32、Uint32N、Uint64、Uint64N、UintN
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
r := rand.New(rand.NewPCG(42, 123))
fmt.Printf("Int32: %d\n", r.Int32())
fmt.Printf("Int64: %d\n", r.Int64())
fmt.Printf("Uint32: %d\n", r.Uint32())
fmt.Printf("IntN(100): %d\n", r.IntN(100))
fmt.Printf("Float64: %f\n", r.Float64())
}
五、Source 类型
Source 接口
定义:
type Source interface {
Uint64() uint64
}
说明:
- 功能:随机源接口
- 要求:实现 Uint64() 方法
- 用途:实现自定义随机数生成器
六、Zipf 类型
Zipf 结构体
定义:
type Zipf struct {
// 包含未导出的字段
}
说明:
- 功能:齐夫分布随机数生成器
- 用途:模拟符合齐夫定律的分布
NewZipf
定义:
func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf
说明:
- 功能:创建 Zipf 分布生成器
- 参数:
r- Rand 实例s- 指数参数(> 1)v- 偏移参数(> 0)imax- 最大值
- 返回值:
*Zipf
示例:
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
r := rand.New(rand.NewPCG(42, 123))
// 创建 Zipf 分布
zipf := rand.NewZipf(r, 2.0, 1.0, 100)
// 生成 Zipf 分布随机数
fmt.Println("Zipf 分布样本:")
for i := 0; i < 10; i++ {
fmt.Printf("%d ", zipf.Uint64())
}
}
Zipf 方法
Uint64
定义:
func (z *Zipf) Uint64() uint64
说明:
- 功能:生成符合 Zipf 分布的随机数
七、典型示例
示例 1:生成随机密码
package main
import (
"fmt"
"math/rand/v2"
)
func generatePassword(length int) string {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"
password := make([]byte, length)
for i := 0; i < length; i++ {
password[i] = charset[rand.IntN(len(charset))]
}
return string(password)
}
func main() {
fmt.Println("随机密码生成:")
for i := 0; i < 5; i++ {
fmt.Printf("%d: %s\n", i+1, generatePassword(12))
}
}
示例 2:使用 PCG 生成可重现序列
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 使用相同种子创建两个相同的生成器
pcg1 := rand.NewPCG(42, 123)
pcg2 := rand.NewPCG(42, 123)
r1 := rand.New(pcg1)
r2 := rand.New(pcg2)
fmt.Println("两个生成器应产生相同序列:")
for i := 0; i < 5; i++ {
n1 := r1.IntN(100)
n2 := r2.IntN(100)
fmt.Printf("r1: %d, r2: %d, 相同:%v\n", n1, n2, n1 == n2)
}
}
示例 3:蒙特卡洛模拟(计算π)
package main
import (
"fmt"
"math/rand/v2"
)
func estimatePi(samples int) float64 {
inside := 0
for i := 0; i < samples; i++ {
x := rand.Float64()
y := rand.Float64()
// 检查点是否在单位圆内
if x*x + y*y <= 1 {
inside++
}
}
// π/4 ≈ inside/samples
return 4.0 * float64(inside) / float64(samples)
}
func main() {
fmt.Println("蒙特卡洛方法估算π:")
samples := []int{1000, 10000, 100000, 1000000}
for _, n := range samples {
pi := estimatePi(n)
fmt.Printf("样本数 %7d: π ≈ %.6f\n", n, pi)
}
}
示例 4:使用泛型函数 N
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
// 使用泛型函数生成各种类型的随机数
fmt.Printf("int8: %d\n", rand.N[int8](100))
fmt.Printf("int16: %d\n", rand.N[int16](1000))
fmt.Printf("int32: %d\n", rand.N[int32](10000))
fmt.Printf("int64: %d\n", rand.N[int64](1000000))
fmt.Printf("uint8: %d\n", rand.N[uint8](100))
fmt.Printf("uint16: %d\n", rand.N[uint16](1000))
fmt.Printf("uint32: %d\n", rand.N[uint32](10000))
fmt.Printf("uint64: %d\n", rand.N[uint64](1000000))
}
示例 5:模拟掷骰子
package main
import (
"fmt"
"math/rand/v2"
)
func rollDice(sides int) int {
return rand.IntN(sides) + 1
}
func rollMultipleDice(count, sides int) []int {
results := make([]int, count)
for i := 0; i < count; i++ {
results[i] = rollDice(sides)
}
return results
}
func main() {
fmt.Println("掷骰子模拟:")
// 掷 10 次 6 面骰
fmt.Println("\n10 次 d6:")
for i := 0; i < 10; i++ {
fmt.Printf("%d ", rollDice(6))
}
// 掷 5 次 20 面骰
fmt.Println("\n\n5 次 d20:")
for i := 0; i < 5; i++ {
fmt.Printf("%d ", rollDice(20))
}
// 3 个 6 面骰
fmt.Println("\n\n3d6 (5 次):")
for i := 0; i < 5; i++ {
rolls := rollMultipleDice(3, 6)
sum := 0
for _, r := range rolls {
sum += r
}
fmt.Printf("%v = %d\n", rolls, sum)
}
}
示例 6:并发安全的随机数生成
package main
import (
"fmt"
"math/rand/v2"
"sync"
)
// 线程安全的随机数生成器
type SafeRand struct {
mu sync.Mutex
r *rand.Rand
}
func NewSafeRand(seed1, seed2 uint64) *SafeRand {
return &SafeRand{
r: rand.New(rand.NewPCG(seed1, seed2)),
}
}
func (sr *SafeRand) IntN(n int) int {
sr.mu.Lock()
defer sr.mu.Unlock()
return sr.r.IntN(n)
}
func (sr *SafeRand) Float64() float64 {
sr.mu.Lock()
defer sr.mu.Unlock()
return sr.r.Float64()
}
func main() {
safeRand := NewSafeRand(42, 123)
var wg sync.WaitGroup
results := make([]int, 10)
// 并发生成随机数
for i := 0; i < 10; i++ {
wg.Add(1)
go func(idx int) {
defer wg.Done()
results[idx] = safeRand.IntN(100)
}(i)
}
wg.Wait()
fmt.Println("并发安全的随机数:")
fmt.Println(results)
}
示例 7:使用 ChaCha8 加密随机源
package main
import (
"crypto/rand"
"fmt"
"math/rand/v2"
)
func main() {
// 生成加密安全的种子
var seed [32]byte
if _, err := rand.Read(seed[:]); err != nil {
panic(err)
}
// 创建 ChaCha8 随机源
chacha := rand.NewChaCha8(seed)
r := rand.New(chacha)
fmt.Println("ChaCha8 随机数生成:")
for i := 0; i < 10; i++ {
fmt.Printf("%d ", r.IntN(100))
}
fmt.Println()
}
示例 8:抽奖系统
package main
import (
"fmt"
"math/rand/v2"
)
type Lottery struct {
participants []string
winners []string
}
func NewLottery() *Lottery {
return &Lottery{
participants: make([]string, 0),
winners: make([]string, 0),
}
}
func (l *Lottery) AddParticipant(name string) {
l.participants = append(l.participants, name)
}
func (l *Lottery) DrawWinners(count int) []string {
if count > len(l.participants) {
count = len(l.participants)
}
// 复制参与者列表
pool := make([]string, len(l.participants))
copy(pool, l.participants)
// 抽取获奖者
winners := make([]string, 0, count)
for i := 0; i < count; i++ {
idx := rand.IntN(len(pool))
winners = append(winners, pool[idx])
// 移除已中奖者
pool[idx] = pool[len(pool)-1]
pool = pool[:len(pool)-1]
}
l.winners = append(l.winners, winners...)
return winners
}
func main() {
lottery := NewLottery()
// 添加参与者
participants := []string{"张三", "李四", "王五", "赵六", "钱七",
"孙八", "周九", "吴十", "郑十一", "王十二"}
for _, p := range participants {
lottery.AddParticipant(p)
}
fmt.Println("抽奖系统")
fmt.Printf("参与者:%d 人\n", len(participants))
// 抽取 3 名获奖者
fmt.Println("\n开始抽奖...")
winners := lottery.DrawWinners(3)
fmt.Println("\n获奖者名单:")
for i, w := range winners {
fmt.Printf("%d. %s\n", i+1, w)
}
}
八、最佳实践
1. 使用包级别函数(简单场景)
// ✓ 好的做法:简单场景使用包级别函数
n := rand.IntN(100)
f := rand.Float64()
// 包级别函数是线程安全的
2. 使用 PCG 或 ChaCha8(需要控制种子)
// ✓ 好的做法:需要重现性时使用 PCG
pcg := rand.NewPCG(42, 123)
r := rand.New(pcg)
n1 := r.IntN(100)
// ✓ 好的做法:需要更高质量随机数使用 ChaCha8
var seed [32]byte
cryptoRand.Read(seed[:])
chacha := rand.NewChaCha8(seed)
r := rand.New(chacha)
3. 使用泛型函数 N
// ✓ 好的做法:使用泛型函数
n := rand.N[int16](1000)
u := rand.N[uint32](10000)
4. 并发场景使用锁
// ✓ 好的做法:并发时使用锁
type SafeRand struct {
mu sync.Mutex
r *rand.Rand
}
5. 安全敏感场景使用 crypto/rand
// ✗ 错误:不应用于安全场景
password := rand.IntN(1000000) // 不安全!
// ✓ 好的做法:使用 crypto/rand
import "crypto/rand"
九、与其他包配合
1. 与 crypto/rand 配合
import (
"crypto/rand"
"math/big"
mrand "math/rand/v2"
)
// 生成加密安全的种子
var seed [32]byte
rand.Read(seed[:])
// 使用 ChaCha8
chacha := mrand.NewChaCha8(seed)
r := mrand.New(chacha)
2. 与 slices 包配合
import (
"math/rand/v2"
"slices"
)
// 打乱切片
slices.Shuffle(data, func(i, j int) {
data[i], data[j] = data[j], data[i]
})
十、快速参考
包级别函数
| 函数 | 参数 | 返回值 | 功能 |
|---|---|---|---|
ExpFloat64 | 无 | float64 | 指数分布 |
Float32 | 无 | float32 | [0,1) 随机 float32 |
Float64 | 无 | float64 | [0,1) 随机 float64 |
Int | 无 | int | 随机非负 int |
Int32 | 无 | int32 | 随机 32 位 int |
Int32N | n int32 | int32 | [0,n) 随机 int32 |
Int64 | 无 | int64 | 随机 64 位 int |
Int64N | n int64 | int64 | [0,n) 随机 int64 |
IntN | n int | int | [0,n) 随机 int |
N | n Int | Int | 泛型 [0,n) 随机数 |
NormFloat64 | 无 | float64 | 标准正态分布 |
Perm | n int | []int | [0,n) 随机排列 |
Shuffle | n int, swap | 无 | 打乱序列 |
Uint | 无 | uint | 随机 uint |
Uint32 | 无 | uint32 | 随机 uint32 |
Uint32N | n uint32 | uint32 | [0,n) 随机 uint32 |
Uint64 | 无 | uint64 | 随机 uint64 |
Uint64N | n uint64 | uint64 | [0,n) 随机 uint64 |
UintN | n uint | uint | [0,n) 随机 uint |
随机源类型
| 类型 | 构造函数 | 特点 |
|---|---|---|
PCG | NewPCG(seed1, seed2 uint64) | 高质量 PCG 生成器 |
ChaCha8 | NewChaCha8(seed [32]byte) | 加密安全生成器 |
v1 vs v2 变化
| v1 | v2 | 说明 |
|---|---|---|
Int31 | Int32 | 32 位整数 |
Int31n | Int32N | 命名规范化 |
Int63 | Int64 | 64 位整数 |
Int63n | Int64N | 命名规范化 |
Intn | IntN | 命名规范化 |
| - | Uint32 | 新增 |
| - | Uint32N | 新增 |
| - | Uint64 | 新增 |
| - | Uint64N | 新增 |
| - | UintN | 新增 |
| - | N | 泛型支持 |
十一、注意事项
1. 不适用于安全场景
// ✗ 不安全的做法
token := rand.Int64() // 可预测!
// ✓ 安全的做法
import "crypto/rand"
n, _ := rand.Int(rand.Reader, big.NewInt(1000000))
2. 并发安全
// 包级别函数是线程安全的
// Rand 对象不是线程安全的,需要加锁
3. 范围验证
// n <= 0 会 panic
rand.IntN(0) // panic!
rand.IntN(-1) // panic!
// ✓ 好的做法
if n > 0 {
rand.IntN(n)
}
4. v2 的优势
- 更好的 API 命名(Int32、Int64 等)
- 新增 Uint 系列函数
- 支持泛型函数 N
- 提供 PCG 和 ChaCha8 两种高质量随机源
- 自动种子化
最后更新: 2026-04-05
Go 版本: Go 1.22+
包文档: https://pkg.go.dev/math/rand/v2