50

Can anyone please tell me why the Go example here:

https://tour.golang.org/basics/1

always returns the same value for rand.Intn(10)?

appliedJames
  • 623
  • 1
  • 5
  • 6
  • 2
    The note on the side says why it is that way: "Note: the environment in which these programs are executed is deterministic, so each time you run the example program rand.Intn will return the same number." – Bojan B Sep 16 '16 at 10:47
  • 1
    @BojanB I saw that but I thought seeding would fix it. icza (see accepted answer) pointed me in the right directions. – appliedJames Sep 16 '16 at 10:54

3 Answers3

79

2 reasons:

  1. You have to initalize the global Source used by rand.Intn() and other functions of the rand package using rand.Seed(). For example:

    rand.Seed(time.Now().UnixNano())
    

    See possible duplicate of Difficulty with Go Rand package.
    Quoting from package doc of rand:

    Top-level functions, such as Float64 and Int, use a default shared Source that produces a deterministic sequence of values each time a program is run. Use the Seed function to initialize the default Source if different behavior is required for each run.

  2. The Tour runs examples on the Go Playground which caches its output.
    See details at Why does count++ (instead of count = count + 1) change the way the map is returned in Golang.

Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827
  • I included "time" in the imports and put that line before the rand.Intn line but now it just returns 0 every time. – appliedJames Sep 16 '16 at 10:45
  • @appliedJames Please also see reason #2. If you still have problems, edit your question and post your code. Aim for a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – icza Sep 16 '16 at 10:46
  • OK thank you that all clears it up. In fact, this whole question should probably be deleted. :) – appliedJames Sep 16 '16 at 10:49
  • I Go PLayground ok...why on my local machine I have the same 1 for any run. – Sever Jul 15 '20 at 21:05
  • Is there a way to embed the seed in the function call instead of having it be a globally set shared value? Thanks. – Julian Hernandez Jan 17 '22 at 19:11
  • @JulianHernandez Yes, you could embed it, but it's a really bad idea. Seeding only needs to be done once. Why slow down every function invocation for something unnecessary? – icza Jan 17 '22 at 19:51
8

For the functions in the rand package to work you have to set a 'Seed' value. This has to be a good random value as decided by the user because - as per https://golang.org/pkg/math/rand/#Rand.Seed this is the value golang uses to set the system to a deterministic state first to then generate a number based on that value.

For the sample code to work, you can try

func main() {
    rand.Seed(time.Now().UnixNano())
    fmt.Println("My favorite number is ", rand.Intn(10))
}

time.Now().UnixNano can give an arbitrary(like) number as the value is in 'one thousand-millionth of a second'

QVSJ
  • 1,165
  • 2
  • 12
  • 22
1

As explained you have to initalize the global Source used by rand.Intn() and other functions of the rand package.

Besides using rand.Seed() option, you also can create the source using the methods rand.NewSource() and rand.New().

source := rand.NewSource(time.Now().UnixNano())
r := rand.New(source)
randomNumber := r.Intn(10)

fmt.Println("A random number: ", randomNumber)
valdeci
  • 13,962
  • 6
  • 55
  • 80
  • I believe the `source` generated by `rand.NewSource` is not safe for concurrent use so you might need to take an extra look at that. – Kwaku Biney Mar 14 '23 at 19:01