How do you generate a random uint64 in Go?
Asked Answered
B

5

11

Go's math/random library is missing a function to generate 64-bit numbers. This has been an open issue for about four years. In the meantime, what does a workaround look like?

Birkett answered 28/9, 2016 at 19:31 Comment(3)
That issue suggested using two random uint32's, any reason that doesn't work for you?Barham
you can shift-OR two int32 numbers, or something similar. You can also use the crypto/rand package and copy a byte buffer to a uint64.Gael
This should be fixed before the 1.8 release cycle is over at the end of October: go-review.googlesource.com/c/27253/1Piet
D
14

Edit: Go 1.8 added a rand.Uint64() function and a Rand.Uint64() method, so you can directly use those.

The rest of the answer pre-dates Go 1.8.


The easiest would be to call rand.Uint32() twice:

func Uint64() uint64 {
    return uint64(rand.Uint32())<<32 + uint64(rand.Uint32())
}

Another option is to call rand.Read() (was added in Go 1.7) to read 8 bytes, then use the encoding/binary package to obtain a uint64 value from it:

func Uint64() uint64 {
    buf := make([]byte, 8)
    rand.Read(buf) // Always succeeds, no need to check error
    return binary.LittleEndian.Uint64(buf)
}

Note: as the doc of rand.Read() states, it always reads as many bytes as the length of the passed slice, and it always returns nil error, so no need to check error in this case.

Note #2: you could also use binary.BigEndian instead of binary.LittleEndian, as we're generating a random number using all its bytes, order of bytes is completely irrelevant.

Drumhead answered 28/9, 2016 at 19:41 Comment(0)
S
7

You can call rand.Uint64() directly: r := rand.Uint64()

Uint64 returns a pseudo-random 64-bit value as a uint64 from the default Source.

https://golang.org/pkg/math/rand/#Uint64

This is available in versions 1.8 and up: changelog

Scrumptious answered 14/4, 2018 at 13:31 Comment(1)
Note that this would not be cryptographically secure and therefore not suitable for many applications.Hedve
C
3

You can also read 8 random bytes, and convert to a uint64

b := make([]byte, 8)
_, err := rand.Read(b)
return binary.LittleEndian.Uint64(b), err
Charlenacharlene answered 28/9, 2016 at 19:43 Comment(0)
A
0

while using crypto/rand is more secure than math/rand and some linter complaining about it with G404: Use of weak random number generator (math/rand instead of crypto/rand)

I recommend something like the following function

func Int64() int64 {
nBig, err := cryptoRand.Int(cryptoRand.Reader, big.NewInt(math.MaxInt64))
if err != nil {
    return 0
}
return nBig.Int64()

}

Antimonous answered 4/1, 2024 at 22:42 Comment(0)
M
0

JFYI.

As of Go 1.22, math/rand/v2 is available. Still pseudo-random (non-secure random) though.

package main

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

func Example_rand_uint64() {
    // Create and seed the generator.
    // Typically a non-fixed seed should be used, such as Uint64(), Uint64().
    // Using a fixed seed will produce the same output on every run.
    r := rand.New(rand.NewPCG(1, 2))

    randUint64 := r.Uint64()

    fmt.Printf("%x\n", randUint64)
    //
    // Output: c4f5a58656eef510
}
Meristic answered 25/7, 2024 at 18:46 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.