You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言中math/rand生成的随机数可预测,如何生成真随机数?

为什么Golang中用math/rand生成的随机数始终可预测?如何生成真随机数?

我尝试用math/rand包生成随机整数作为临时令牌,但每次运行程序时生成的随机数序列都一模一样,完全可预测。我甚至在调用rand.Intn(100000)之前调用了Seed()函数,用rand.Seed(rand.Intn(500))来设置种子,但生成的数字还是可以预测。请问在Golang里有没有生成真随机数的方法?

我的代码如下:

rand.Seed(rand.Intn(500))
fmt.Println(rand.Intn(100000))

你踩了math/rand的一个常见坑啦!math/rand本身是伪随机数生成器,它的随机性完全依赖于初始种子——如果种子相同,生成的序列就完全一样。你用rand.Intn(500)来当种子的问题在于:程序启动时math/rand的默认种子是固定的(默认值为1),所以每次运行时rand.Intn(500)的结果其实也是固定的,等于没换种子!

要生成不可预测的随机数,你需要用crypto/rand包,它是基于系统提供的真随机源(比如Linux的/dev/urandom、Windows的CryptGenRandom)来生成安全的随机数,适合做令牌、密钥这类需要不可预测性的场景。

给你两个实用方案:

方案1:直接用crypto/rand生成安全随机整数

如果只是需要生成指定范围的随机整数,可以这样写:

package main

import (
    "crypto/rand"
    "fmt"
    "math/big"
)

func main() {
    // 生成0到99999之间的随机数(包含0,不包含100000)
    max := big.NewInt(100000)
    randomNum, err := rand.Int(rand.Reader, max)
    if err != nil {
        // 实际项目中建议更优雅的错误处理,这里用panic做示例
        panic(err)
    }
    fmt.Println(randomNum.Int64())
}

方案2:用crypto/rand给math/rand设置种子(适合需要序列随机的场景)

如果你还是想继续用math/rand的API,那得用crypto/rand生成一个真正随机的种子:

package main

import (
    "crypto/rand"
    "fmt"
    "math/big"
    "math/rand"
)

func main() {
    // 生成一个随机的int64种子
    seed, err := rand.Int(rand.Reader, big.NewInt(1<<63-1))
    if err != nil {
        panic(err)
    }
    rand.Seed(seed.Int64())
    // 现在生成的随机数就不可预测了
    fmt.Println(rand.Intn(100000))
}

另外补充个小知识点:从Go 1.20开始,math/rand的默认种子已经改成从crypto/rand获取的随机值,也就是说如果你用的是Go 1.20+版本,甚至不需要手动调用Seed(),直接用rand.Intn()就能得到不可预测的随机数了!不过老版本还是得按上面的方法来处理。


内容的提问来源于stack exchange,提问作者Micheal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:27:55