go生成随机数

2025-04-08T12:39:00

在 Go 语言中,我们通常使用两种包来生成随机数,分别是用于生成伪随机数的 math/rand 包和用于生成加密安全随机数的 crypto/rand 包。

使用 math/rand

  1. 生成随机数math/rand 包提供了如 rand.Int()rand.Intn(n)(生成 0 到 n-1 的整数)和 rand.Float64()(生成范围在 0.0, 1.0) 的浮点数)等函数,可以用来生成伪随机数[3。
  2. 设置种子
    默认情况下,math/rand 使用的是固定的随机种子,这意味着每次程序运行时生成的随机数序列都是相同的。为了使随机数每次都不同,我们需要调用 rand.Seed() 方法,并通常传入 time.Now().UnixNano() 作为种子,例如:

    package main
    
    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    func main() {
        // 通过当前时间的纳秒数来设置种子,确保每次运行生成不同的随机序列
        rand.Seed(time.Now().UnixNano())
    
        // 生成一个在 0 到 99 范围内的随机整数
        fmt.Println(rand.Intn(100)) // [1][2]
    
        // 生成一个在 [0.0, 1.0) 范围内的随机浮点数
        fmt.Println(rand.Float64()) // [3]
    }

    如果不设置种子,那么会生成相同的数字序列,这对于大多数需要随机性的场景来说是不合适的。

使用 crypto/rand

如果需要生成加密安全的随机数,比如用于生成密钥、令牌等敏感信息时,可以使用 crypto/rand 包。该包提供的随机数生成方法与 math/rand 不同,并且生成的随机数适合用在需要高随机性保障的场景中。

crypto/rand内部使用操作系统提供的随机性资源,因此不需要也不能通过设置种子来改变随机结果。

基本使用方式

  1. 生成随机字节
    常见的做法是先生成一个字节切片,然后利用 io.ReadFullrand.Reader 中读取随机数据填充到该切片中。例如,可以生成一个 32 字节的随机数组,并将其用于生成 session ID:

    package main
    
    import (
        "crypto/rand"
        "encoding/base64"
        "fmt"
        "io"
    )
    
    func sessionId() string {
        b := make([]byte, 32)
        // 从 rand.Reader 中精确读取 32 字节数据填充到 b 中
        if _, err := io.ReadFull(rand.Reader, b); err != nil {
            panic(err)
        }
        // 对生成的字节数组进行 base64 编码,作为 session ID 返回
        return base64.URLEncoding.EncodeToString(b)
    }
    
    func main() {
        fmt.Println("Session ID:", sessionId())
    }

    这里我们不需要设置种子,而是直接依赖操作系统安全地生成随机数。

  2. 生成安全随机整数
    如果需要生成一个加密安全的随机整数,可以使用 rand.Int 函数,这个函数接受一个 io.Reader(通常使用 rand.Reader)和一个 big.Int 类型的上限。例如,生成范围在 [0, max) 内的随机整数:

    package main
    
    import (
        "crypto/rand"
        "fmt"
        "math/big"
    )
    
    func main() {
        max := big.NewInt(28) // 生成的随机数将介于 0 到 27 之间
        n, err := rand.Int(rand.Reader, max)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        fmt.Println("Secure Random Number:", n)
    }

    这种方式可以确保生成的整数在加密安全方面满足要求,非常适合生成密钥、令牌等场景。

随机生成三位数

下面给出一个示例代码,展示如何使用 Go 语言中的 crypto/rand 包来生成一个三位数(即 100~999 范围内的随机整数)。这种方法使用了 rand.Int 函数生成一个区间内的随机大数,再通过加上偏移量得到最终的结

package main

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

func main() {
    // 我们希望生成100至999之间的随机数,共900个可能值(0~899,然后加上100)
    n, err := rand.Int(rand.Reader, big.NewInt(900)) // 生成区间 [0,900) 内的随机数
    if err != nil {
        panic(err)
    }
    result := n.Int64() + 100 // 加上100,变换到 [100, 999] 区间
    fmt.Println("随机生成的三位数是:", result)
}

这里说明几点:

  • 使用 rand.Int(rand.Reader, big.NewInt(900)) 能确保生成的随机数是加密安全的,并且不需要设置种子,因为它直接调用了操作系统的随机资源。
  • 生成的随机数范围是 [0,899],再加上 100 后就得到了三位数 [100, 999] 的结果。
当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »