TTuck

Go's math/rand/v2 package provides pseudorandom number generation. For anything security related, such as tokens and keys, use crypto/rand instead.

package main

import (
	crand "crypto/rand"
	"fmt"
	"math/rand/v2"
)

func main() {

For example, rand.IntN returns a random int n, 0 <= n < 100. The output differs between runs, so we only check the range here.

	n := rand.IntN(100)
	fmt.Println("0 <= n < 100:", n >= 0 && n < 100)

rand.Float64 returns a float64 f, 0.0 <= f < 1.0.

	f := rand.Float64()
	fmt.Println("0 <= f < 1:", f >= 0 && f < 1)

This can be used to generate random floats in other ranges, for example 5.0 <= f' < 10.0.

	g := rand.Float64()*5 + 5
	fmt.Println("5 <= g < 10:", g >= 5 && g < 10)

If you want a known seed, create a new rand.Source and pass it into the New constructor. NewPCG creates a new PCG source that requires a seed of two uint64 numbers. A seeded generator gives the same sequence every time.

	s2 := rand.NewPCG(42, 1024)
	r2 := rand.New(s2)
	fmt.Print(r2.IntN(100), ",")
	fmt.Print(r2.IntN(100))
	fmt.Println()

	s3 := rand.NewPCG(42, 1024)
	r3 := rand.New(s3)
	fmt.Print(r3.IntN(100), ",")
	fmt.Print(r3.IntN(100))
	fmt.Println()

Shuffle and Perm rearrange values; with a seeded generator they repeat too.

	words := []string{"a", "b", "c", "d", "e"}
	r4 := rand.New(rand.NewPCG(1, 2))
	r4.Shuffle(len(words), func(i, j int) { words[i], words[j] = words[j], words[i] })
	fmt.Println(words, r4.Perm(5))

crypto/rand reads from the operating system's secure source. rand.Text returns a random string suitable for tokens.

	token := crand.Text()
	key := make([]byte, 16)
	crand.Read(key)
	fmt.Println("token length:", len(token), "key bytes:", len(key))
}
$ go run ./67_random_numbers
0 <= n < 100: true
0 <= f < 1: true
5 <= g < 10: true
94,49
94,49
[b e c a d] [2 3 4 0 1]
token length: 26 key bytes: 16