Выберите случайное значение из фрагмента Go
Ситуация:
У меня есть часть значений, и мне нужно выбрать случайно выбранное значение. Затем я хочу объединить его с фиксированной строкой. Пока это мой код:
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 )
}
Вопрос:
Есть ли встроенная функция, которая может помочь мне, выполнив часть "выберите случайную причину"?
Ответы
Ответ 1
Используйте функцию Intn
из пакета rand
, чтобы выбрать случайный индекс.
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))
Ответ 2
Просто выберите длину фрагмента случайного целого числа:
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
.)
Ответ 3
Так как это все еще отображается в лучших результатах Google для генерации случайных строк 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
Исходя из этого, я скопировал getRandomUint32() из fastrand: https://github.com/valyala/fastrand
И решение предложено выше. Производительность не сильно отличается, но я хотел поделиться результатами.
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
Эти результаты запускались только несколько раз локально, и я взял то, что казалось медианным результатом. Безусловно, предстоит проделать еще больше работы с точки зрения итераций и тому подобного, но я просто хотел поделиться тем, что у меня есть.