String 如何使用字符串作为Golang中rand.Seed()函数的输入?
我想做什么: 基于字符串的内容(例如,String 如何使用字符串作为Golang中rand.Seed()函数的输入?,string,go,random,seed,random-seed,String,Go,Random,Seed,Random Seed,我想做什么: 基于字符串的内容(例如,a1b2c3d4e5),我想生成一组“可重复”的随机事件。在Golang中生成可重复的随机数很容易-您只需使用函数为随机数生成器添加特定数字的种子,然后就完成了 但是,该函数将int64作为参数。因此,我需要以某种方式将字符串转换为int64 我已经尝试过的: 我的第一个想法是使用base64对字符串进行编码,然后将字节序列转换为int64。然而,通过一些基本的测试,似乎只支持长度约为7的字符串。添加第8个字符后,数字保持不变 我想这里的基本问题是,可能的字
a1b2c3d4e5
),我想生成一组“可重复”的随机事件。在Golang中生成可重复的随机数很容易-您只需使用函数为随机数生成器添加特定数字的种子,然后就完成了
但是,该函数将int64作为参数。因此,我需要以某种方式将字符串转换为int64
我已经尝试过的:
我的第一个想法是使用base64对字符串进行编码,然后将字节序列转换为int64。然而,通过一些基本的测试,似乎只支持长度约为7的字符串。添加第8个字符后,数字保持不变
我想这里的基本问题是,可能的字符串值比可能的int64值多
那么某种散列函数呢?据我所知,大多数散列函数都返回一个字节序列;我需要某种返回int64的哈希函数。也许这种方法也被误导了?使用哈希函数是一个好的方向。要生成适合
int64
的值,只需获取散列值的前8个字节
对于一个好的散列函数,散列结果的每个字节(或者更确切地说,每个位)都取决于所有的输入字节,因此前8个字节不会在特定的输入长度后被“卡住”
要将8个字节的片转换为int64
值,可以使用包
例如:
digest := ... // calculate digest
seed := int64(binary.BigEndian.Uint64(digest[:8]))
切片摘要值
digest[:8]
也可以省略,因为BigEndian.Uint64()
调用将只读取前8个字节。字符串的散列将完成此操作
您可以使用:
- 字符串的总和(返回16个字节)
- 将前8个字节转换为uint64(忽略其余部分。但如果输入少于8个字节,则会崩溃)
2458341265858962012
792667671
注意:md5只是一个例子。您可以使用生成至少8个字节的任何哈希。例:。只需将md5.New()
替换为sha256.New()
(以及导入)。
您可以找到一个很好的哈希示例列表
还有一个大字是警告:这根本不涉及加密应用程序。我假设这是用户提供的种子(例如:游戏种子),用于非加密目的。你可以试试。通过使用时间生成不同的种子,可以为生成随机事件提供不同的序列
package main
import (
"bytes"
"fmt"
"math/rand"
"time"
)
var r = rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
func main() {
fmt.Println(randomString(10))
}
func randomString(l int) string {
var result bytes.Buffer
var temp string
for i := 0; i < l; {
if string(randInt(65, 90)) != temp {
temp = string(randInt(65, 90))
result.WriteString(temp)
i++
}
}
return result.String()
}
func randInt(min int, max int) int {
return min + r.Intn(max-min)
}
主程序包
进口(
“字节”
“fmt”
“数学/兰德”
“时间”
)
var r=rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
func main(){
格式打印项次(随机字符串(10))
}
func随机字符串(l int)字符串{
var结果字节。缓冲区
变量临时字符串
对于i:=0;i
出于安全原因,是否要求种子不易从输入字符串中操作/检测?因为如果不是的话,我想不出任何理由为什么仅仅对字符串进行任何哈希并应用mod MAXINT
是不够的。CRC64不是比MD5(或SHA256)更好的哈希算法吗,因为它只输出64位,因此不必忽略/截断任何内容?这肯定会起作用。如果这是一个游戏的随机数生成器,这将是完美的。然而,如果这是为了加密目的而为随机数生成器播种,那么sha256可能是迄今为止提到的三种方法中最好的一种。这是为了一个游戏。你能在CRC64的例子中编辑吗?CRC64使用起来有点烦人。您可以在我添加到答案的链接中看到示例(以及Go中的许多其他哈希)。
package main
import (
"bytes"
"fmt"
"math/rand"
"time"
)
var r = rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
func main() {
fmt.Println(randomString(10))
}
func randomString(l int) string {
var result bytes.Buffer
var temp string
for i := 0; i < l; {
if string(randInt(65, 90)) != temp {
temp = string(randInt(65, 90))
result.WriteString(temp)
i++
}
}
return result.String()
}
func randInt(min int, max int) int {
return min + r.Intn(max-min)
}