Go有两个随机数的包:
crypto/rand
,它提供了获取随机字节的方法math/rand
,它有一个很好的改组整数算法我想使用Perm
中的math/rand
算法,但为其提供高质量的随机数。
由于两个rand
包是同一标准库的一部分,因此应该有一种方法以某种方式组合它们,以便crypto/rand
提供math/rand.Perm
使用的随机数的良好来源。 1}}生成排列。
这里(以及Playground)是我为连接这两个包而编写的代码:
package main
import (
cryptoRand "crypto/rand"
"encoding/binary"
"fmt"
mathRand "math/rand"
)
type cryptoSource struct{}
func (s cryptoSource) Int63() int64 {
bytes := make([]byte, 8, 8)
cryptoRand.Read(bytes)
return int64(binary.BigEndian.Uint64(bytes) >> 1)
}
func (s cryptoSource) Seed(seed int64) {
panic("seed")
}
func main() {
rnd := mathRand.New(&cryptoSource{})
perm := rnd.Perm(52)
fmt.Println(perm)
}
此代码有效。理想情况下,我不想自己定义cryptoSource
类型,而只是将两个rand
包粘在一起,以便它们协同工作。那么这个cryptoSource
类型的预定义版本是什么?
答案 0 :(得分:2)
这基本上就是你需要做的。对于math/rand
的常见用法,您通常不需要加密安全的随机源,因此没有提供适配器。通过直接在结构中分配缓冲区空间,而不是在每次调用时分配新的切片,可以使实现略微提高效率。
type cryptoSource struct {
buf [8]byte
}
func (s *cryptoSource) Int63() int64 {
cryptoRand.Read(s.buf[:])
return int64(binary.BigEndian.Uint64(s.buf[:]) & (1<<63 - 1))
}
或者只是将源[8]byte
本身设为
type cryptoSource [8]byte
func (s *cryptoSource) Int63() int64 {
cryptoRand.Read(s[:])
return int64(binary.BigEndian.Uint64(s[:]) & (1<<63 - 1))
}