【问题标题】:Generating a random, fixed-length byte array in Go在 Go 中生成一个随机的、固定长度的字节数组
【发布时间】:2016-06-17 07:28:33
【问题描述】:

我有一个字节数组,固定长度为 4。

token := make([]byte, 4)

我需要将每个字节设置为随机字节。我怎么能这样做,以最有效的方式?就我而言,math/rand 方法不提供随机字节函数。

也许有一种内置方式,或者我应该生成一个随机字符串并将其转换为字节数组?

【问题讨论】:

  • 1.您有一个字节切片(不是数组)。 2. 在需要之前不要担心效率。 3.)考虑crypto/rand而不是math/rand(或偶尔来自crypto/rand的种子math/rand)。 4) io.ReadFull 很方便。

标签: arrays go random slice


【解决方案1】:

Go 1.6 向 math/rand 包添加了一个新功能:

func Read(p []byte) (n int, err error)

它用随机数据填充传递的byte 切片。使用这个rand.Read()

token := make([]byte, 4)
if _, err := rand.Read(token); err != nil {
    // Handle err
}
fmt.Println(token)

rand.Read() 有 2 个返回值:“读取”字节数和(可选)error。这是为了符合一般的io.Reader 接口,但rand.Read() 的文档指出(尽管有签名)它实际上永远不会返回非nil 错误,所以我们可以省略检查它,这将其简化为这个:

token := make([]byte, 4)
rand.Read(token)
fmt.Println(token)

在使用math/rand 包之前不要忘记调用rand.Seed() 以正确初始化它,例如:

rand.Seed(time.Now().UnixNano())

注意:在 Go 1.6 之前,没有 math/rand.Read() 函数,但有(现在仍然是)crypto/rand.Read() 函数,但 crypto/rand 包实现了加密安全的伪随机数生成器,因此速度要慢得多比math/rand.

【讨论】:

  • rand.Read 总是返回 nil 错误,所以没有必要处理它——即使这是一个受人尊敬的习惯...... :)
  • @Aedolon 是的,刚刚添加了。
【解决方案2】:

使用 math.Rand 意味着您正在使用您的操作系统提供的系统 CSPRNG。这意味着使用 /dev/urandom/ 和 Windows 的 CryptGenRandom API。 幸运的是,Go 的 crypto/rand 包将这些实现细节抽象出来,以尽量减少出错的风险。

import(
   "crypto/rand"
   "encoding/base64"
 )

// GenerateRandomBytes returns securely generated random bytes. 
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
     b := make([]byte, n)
    _, err := rand.Read(b)
    // Note that err == nil only if we read len(b) bytes.
    if err != nil {
       return nil, err
   }

   return b, nil
}

【讨论】:

    【解决方案3】:

    Package rand

    import "math/rand" 
    

    func Read

    func Read(p []byte) (n int, err error)
    

    Read 从默认 Source 生成 len(p) 个随机字节并写入 他们进入p。它总是返回 len(p) 和一个 nil 错误。

    func (*Rand) Read

    func (r *Rand) Read(p []byte) (n int, err error)
    

    Read 生成 len(p) 个随机字节并将它们写入 p。它总是 返回 len(p) 和一个 nil 错误。

    例如,

    package main
    
    import (
        "math/rand"
        "fmt"
    )
    
    func main() {
        token := make([]byte, 4)
        rand.Read(token)
        fmt.Println(token)
    }
    

    输出:

    [187 163 35 30]
    

    【讨论】:

    • 在 rand.Read 之前调用 rand.Seed(),否则每次运行都会得到相同的输出
    猜你喜欢
    • 1970-01-01
    • 2018-06-19
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    • 2019-06-23
    • 2015-09-13
    相关资源
    最近更新 更多