Pick a random value from a Go Slice

前端 未结 3 777
情书的邮戳
情书的邮戳 2021-02-01 00:53

Situation:

I\'ve a slice of values and need to pick up a randomly chosen value from it. Then I want to concatenate it with a fixed string. This is my co

相关标签:
3条回答
  • 2021-02-01 01:35

    Just pick a random integer mod slice length:

    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])
    

    Playground: http://play.golang.org/p/fEHElLJrEZ. (Note the commend about rand.Seed.)

    0 讨论(0)
  • 2021-02-01 01:40

    Since this still shows up in Google's top results for Golang random string generation, I wanted to share what I have been working with.

    Here is the solution I am using:

    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)
    }
    

    And results:

    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
    

    Source wise, I copied getRandomUint32() from fastrand: https://github.com/valyala/fastrand

    And the solution proposed above. Performance isn't all that different, but I wanted to share results.

    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))]
    }
    

    And results:

    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
    

    These results were only run a few times locally and I grabbed what appeared to be the median result. There is certainly more work to be done in terms of iterations and whatnot, but I just wanted to share what I have.

    0 讨论(0)
  • 2021-02-01 01:49

    Use function Intn from rand package to select a random index.

    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))])
    

    Other solution is to use Rand object.

    s := rand.NewSource(time.Now().Unix())
    r := rand.New(s) // initialize local pseudorandom generator 
    r.Intn(len(reasons))
    
    0 讨论(0)
提交回复
热议问题