ZetCode

Go random

last modified August 30, 2026

In this article we show how to generate random values in Go. We use math/rand/v2 for ordinary pseudo-random values and crypto/rand when the values must be unpredictable.

Random number generator

Random number generator (RNG) generates a set of values that do not display any distinguishable patterns in their appearance. The random number generators are divided into two categories: hardware random-number generators and pseudo-random number generators. Hardware random-number generators are believed to produce genuine random numbers. Pseudo-random number generators generate values based on software algorithms. They produce values that look random. But these values are deterministic and can be reproduced, if the algorithm is known.

In computing, random generators are used in gambling, gaming, simulations, or cryptography.

Note: For security purposes, cryptographically secure pseudo-random number generators must be used.

Cryptographically secure generators obtain entropy from the operating system. They are designed to resist prediction and are appropriate for secrets; they are usually slower than ordinary pseudo-random generators.

Go contains the math/rand/v2 package, which implements ordinary pseudo-random number generators, and the crypto/rand package, which implements a cryptographically secure random number generator.

The seed

The seed is a value which initializes the random number generator. Random number generators produce values by performing some operation on a previous value. When the algorithm starts, the seed is the initial value on which the generator operates. The most important and difficult part of the generators is to provide a seed that is close to a truly random number.

For reproducible pseudo-random values, create a local generator with an explicit seed. The package-level functions in math/rand/v2 are automatically seeded for ordinary use, so application code does not need to seed them with the current time.

Note: The same seed produces the same set of pseudo-random numbers.

Go random same seed

In the following example, we use the same seed.

same_seed.go
package main

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

func main() {

    first := rand.New(rand.NewPCG(20, 10))
    fmt.Printf("%d ", first.IntN(100))
    fmt.Printf("%d ", first.IntN(100))
    fmt.Printf("%d \n", first.IntN(100))

    second := rand.New(rand.NewPCG(20, 10))
    fmt.Printf("%d ", second.IntN(100))
    fmt.Printf("%d ", second.IntN(100))
    fmt.Printf("%d \n", second.IntN(100))

    fmt.Println()
}

The same seed values produce the same pseudo-random values. The two 64-bit values passed to NewPCG initialize the generator state.

NewPCG returns a generator based on the PCG (permuted congruential generator) algorithm, which is the default generator of math/rand/v2. The function takes two 64-bit seed values, seed1 and seed2, which together form the initial state of the generator. Generators created with the same seed values produce the same sequence of pseudo-random numbers; using different seed values produces different sequences.

$ go run same_seed.go 
6 2 3
6 2 3

Go rand.IntN

The rand.IntN function returns, as an int, a non-negative pseudo-random number in [0,n) from the default source.

five_random.go
package main

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

func main() {

    for i := 0; i < 5; i++ {

        fmt.Printf("%d ", rand.IntN(20))
    }

    fmt.Println()
}

The example prints five random integers.

rand.IntN(20)

The package-level generator is automatically seeded, so repeated runs normally produce different values without any explicit time-based seed.

Go random string

The following example generates random strings.

random_string.go
package main

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

func main() {

    fmt.Println(randomString(12))
}

func randomString(length int) string {

    bytes := make([]byte, length)

    for i := 0; i < length; i++ {
        bytes[i] = byte('a' + rand.IntN(26))
    }

    return string(bytes)
}

The example creates a random string having twelve characters.

$ go run random_string.go 
gqvqyybfuhxl
$ go run random_string.go 
rrwmqaqkrslu
$ go run random_string.go 
axhhrkwyhnxm

We run the example three times. The output changes because the package-level generator is automatically seeded.

Go random array of integers

The following example creates an array of random integer values.

random_array.go
package main

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

func randArray(len int) []int {

    a := make([]int, len)

    for i := 0; i < len; i++ {

        a[i] = rand.IntN(len)
    }

    return a
}

func main() {

    len := 12
    fmt.Println(randArray(len))
}

The example creates an array of twelve integer values.

$ go run rand_array.go 
[5 6 3 5 3 4 7 3 5 6 5 0]
$ go run rand_array.go 
[2 5 10 9 1 5 1 4 11 7 6 3]

Go random element

The following example picks a random element.

random_element.go
package main

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

func main() {

    runes := []rune("červená čiara")

    myrune := runes[rand.IntN(len(runes))]

    fmt.Println(string(myrune))
}

We have a slice of runes. From this slice, we randomly pick a value.

$ go run random_element.go 
č
$ go run random_element.go 
á

We ran the example twice and get these characters.

Go random string from a pool

The following example picks letters randomly from a pool of characters.

rand_pool.go
package main

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

var pool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:|?$%@][{}#&/*)"

func randomString(l int) string {

    bytes := make([]byte, l)

    for i := 0; i < l; i++ {
        bytes[i] = pool[rand.IntN(len(pool))]
    }

    return string(bytes)
}

func main() {

    fmt.Println(randomString(12))
}

The example prints random strings from the predefined pool of various characters.

var pool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:|?$%@][{}#&/*)"

This is the set of predefined characters.

for i := 0; i < l; i++ {
    bytes[i] = pool[rand.IntN(len(pool))]
}

We pick a random letter by generating a random index of the string.

$ go run rand_pool.go 
FFFZW(sHvE:a
$ go run rand_pool.go 
(my%Tmf&qOVs
$ go run rand_pool.go 
/{GqgkhRVOfi

We run the example three times.

Go crypto-secure random values

Go provides a cryptographically secure pseudorandom number generator in the standard library package crypto/rand. math/rand/v2 is usually faster and is suited for ordinary values, while crypto/rand is suited for programs where security is paramount, such as when generating strong passwords, CSRF tokens, or session keys.

On Linux and FreeBSD, crypto/rand uses getrandom if available, and /dev/urandom otherwise. On OpenBSD, it uses getentropy. On Unix-like systems, it reads from the operating system's secure random source. On Windows systems, it uses the system cryptographic random source. On Wasm, it uses the Web Crypto API.

crypto_rand.go
package main

import (
    "crypto/rand"
    "fmt"
    "log"
)

func main() {

    data, err := generateRandomBytes(16)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(data)
}

func generateRandomBytes(n int) ([]byte, error) {

    b := make([]byte, n)
    _, err := rand.Read(b)
    
    if err != nil {
        return nil, err
    }

    return b, nil
}

In the code example, we create 16 securely generated random bytes.

b := make([]byte, n)
_, err := rand.Read(b)

We read n cryptographically secure pseudorandom numbers and write them into a byte slice.

$ go run crypto_rand.go 
[151 0 67 88 199 60 220 50 34 198 169 158 18 162 85 61]

Source

Go math/rand/v2 package - reference

Go crypto/rand package - reference

In this article we have worked with random values in Golang.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Go tutorials.