math/rand默认种子为1导致每次运行随机数相同,需用time.Now().UnixNano()设种;生成[1,100]整数应写为1+r.Intn(100);并发下应避免全局函数,推荐局部*rand.Rand实例或sync.Pool复用。

为什么 math/rand 生成的随机数每次运行都一样?
因为默认种子(seed)固定为 1,rand.NewSource(1) 导致序列完全可复现。这不是 bug,是设计使然——方便测试,但生产环境必须手动设种。
正确做法是用当前时间纳秒级精度初始化:
src := rand.NewSource(time.Now().UnixNano()) r := rand.New(src)
注意别在循环里反复调用 time.Now() 初始化,否则高并发下可能撞上相同种子;全局复用一个 *rand.Rand 实例更安全。
如何生成指定范围的随机整数(比如 [1, 100])?
rand.Intn(n) 返回 [0, n) 的整数,不能直接套用。要得到闭区间 [min, max],得做偏移和长度校准:
立即学习“go语言免费学习笔记(深入)”;
- 先算长度:
max - min + 1 - 再加偏移:
min + r.Intn(max-min+1)
例如生成 1 到 100(含):
num := 1 + r.Intn(100) // ✅ 不是 r.Intn(100) + 1 写法错误,但语义等价;重点是范围计算别漏 +1
常见错误:写成 r.Intn(100) + 1 看似对,但如果 min 是变量,漏掉 +1 就变成 [min, max) 了。
如何生成随机浮点数或字符串?
math/rand 提供 Float32() 和 Float64(),返回 [0.0, 1.0) 区间值,缩放即可:
网趣购物系统静态版支持网站一键静态生成,采用动态进度条模式生成静态,生成过程更加清晰明确,商品管理上增加淘宝数据包导入功能,与淘宝数据同步更新!采用领先的AJAX+XML相融技术,速度更快更高效!系统进行了大量的实用性更新,如优化核心算法、增加商品图片批量上传、谷歌地图浏览插入等,静态版独特的生成算法技术使静态生成过程可随意掌控,从而可以大大减轻服务器的负担,结合多种强大的SEO优化方式于一体,使
// [5.0, 15.0) f := 5.0 + r.Float64()*10.0
生成随机字符串需组合使用 r.Intn() 和字符集:
const letters = "abcdefghijklmnopqrstuvwxyz0123456789"
b := make([]byte, 8)
for i := range b {
b[i] = letters[r.Intn(len(letters))]
}
s := string(b)注意:不要用 rand.Read() 混淆——那是 crypto/rand 的函数,用于密码学安全场景,性能差、阻塞式,math/rand 不提供该方法。
并发环境下直接用全局 rand.* 函数安全吗?
不安全。rand.Intn() 等全局函数操作的是包级全局变量 rand.Rand,内部用 mutex 保护,但会成为性能瓶颈,且 Go 1.20+ 已标记为「不推荐」。
推荐方式是每个 goroutine 自持实例,或用 sync.Pool 复用:
var randPool = sync.Pool{
New: func() interface{} {
return rand.New(rand.NewSource(time.Now().UnixNano()))
},
}然后在 goroutine 中取用:r := randPool.Get().(*rand.Rand),用完记得 randPool.Put(r)。不过多数服务中,直接用带 seed 的局部 *rand.Rand 更清晰可控。
真正容易被忽略的是:哪怕你用了 sync.Pool,也别把 time.Now().UnixNano() 放在 New 函数里——池中对象可能复用,重复设种反而导致随机性下降。应该在每次 Get 后重置 seed,或干脆只用一次性的实例。









