从 Go Slice 中选择一个随机值

情况:

我有一个值片段,需要从中随机选择一个值。然后我想用一个固定的字符串连接它。到目前为止,这是我的代码:

func main() {
//create the reasons slice and append reasons to it
reasons := make([]string, 0)
reasons = append(reasons,
"Locked out",
"Pipes broke",
"Food poisoning",
"Not feeling well")


message := fmt.Sprint("Gonna work from home...", pick a random reason )
}

问题:

是否有一个内置的功能,可以帮助我做“ 随便找个理由”的一部分?

73287 次浏览

只需选择一个随机整数 mod 片长:

rand.Seed(time.Now().Unix())
reasons := []string{
"Locked out",
"Pipes broke",
"Food poisoning",
"Not feeling well",
}
n := rand.Int() % len(reasons)
fmt.Print("Gonna work from home...", reasons[n])

操场: http://play.golang.org/p/fEHElLJrEZ。(请注意关于 rand.Seed的推荐。)

使用 rand包中的函数 Intn选择一个随机索引。

import (
"math/rand"
"time"
)


// ...


rand.Seed(time.Now().Unix()) // initialize global pseudo random generator
message := fmt.Sprint("Gonna work from home...", reasons[rand.Intn(len(reasons))])

另一种解决方案是使用 Rand对象。

s := rand.NewSource(time.Now().Unix())
r := rand.New(s) // initialize local pseudorandom generator
r.Intn(len(reasons))

由于这仍然显示在谷歌的顶部搜索结果为 Golang 随机字符串生成,我想分享我一直在与什么。

以下是我正在使用的解决方案:

package main


import (
"fmt"
"strings"
"time"
)


var (
opts  = strings.Split("option1,option2,option3", ",")
start = time.Now()
)


func main() {
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
}


func getRandomOpt() string {
len := len(opts)
n := uint32(0)
if len > 0 {
n = getRandomUint32() % uint32(len)
}
return opts[n]
}


func getRandomUint32() uint32 {
x := time.Now().UnixNano()
return uint32((x >> 32) ^ x)
}

结果是:

option2 665ns
option1 41.406µs
option1 44.817µs
option3 47.329µs
option1 49.725µs
option3 52µs
option2 54.393µs
option2 56.798µs
option1 59.098µs

在源代码方面,我从 fastrandhttps://github.com/valyala/fastrand复制了 getRRandom Uint32()

以及上面提出的解决方案。性能并没有那么不同,但我想分享结果。

package main


import (
"fmt"
"math/rand"
"strings"
"time"
)


var (
opts  = strings.Split("option1,option2,option3", ",")
start = time.Now()
)


func main() {
rand.Seed(start.Unix())
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
fmt.Println(getRandomOpt(), time.Since(start))
}


func getRandomOpt() string {
return opts[rand.Intn(len(opts))]
}

结果是:

option3 11.865µs
option2 48.415µs
option3 52.809µs
option1 55.536µs
option3 58.191µs
option3 60.793µs
option1 63.391µs
option2 65.982µs
option2 68.601µs

这些结果只在局部运行了几次,我得到了似乎是中位数的结果。当然,在迭代和其他方面还有更多的工作要做,但我只是想分享我所拥有的。