Skip to content
This repository has been archived by the owner on Oct 21, 2023. It is now read-only.

Commit

Permalink
Change randomness behaviour to be like it prior to go1.20
Browse files Browse the repository at this point in the history
Pre go1.20, rand.Seed needed to be called for randomness. Meaning, that
math/rand delivered deterministic values by default. This was changed
however. To restore the old behaviour, we need to manually seed our
random generator with a constant.

Additionally, this introduce a local instance of rand.Rand, in order
to prevent unexpected behaviour with other code that relies on the
global math/rand package.

Fixes dustinkirkland#10 (The readme and docs explain this, therefore I consider this
solved, as it is by design and not a bug)

Fixes dustinkirkland#15
  • Loading branch information
Bios-Marcel committed Aug 26, 2023
1 parent e794b93 commit 64ecdb6
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 18 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,15 @@ var (
separator = flag.String("separator", "-", "The separator between words in the pet name")
)

func init() {
rand.Seed(time.Now().UTC().UnixNano())
}

func main() {
flag.Parse()
rand.Seed(time.Now().UnixNano())

// To have a predictable series of petnames. (This is the default)
petname.Seed(1)

// To have an unpredictable series of petnames.
petname.NonDeterministicMode()

fmt.Println(petname.Generate(*words, *separator))
}
```
Expand Down
12 changes: 4 additions & 8 deletions cmd/petname/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,18 @@ package main
import (
"flag"
"fmt"
"math/rand"
"time"
"github.com/dustinkirkland/golang-petname"

petname "github.com/dustinkirkland/golang-petname"
)

var (
words = flag.Int("words", 2, "The number of words in the pet name")
words = flag.Int("words", 2, "The number of words in the pet name")
separator = flag.String("separator", "-", "The separator between words in the pet name")
)

func init() {
rand.Seed(time.Now().UTC().UnixNano())
}

func main() {
flag.Parse()
rand.Seed(time.Now().UnixNano())
petname.Seed(time.Now().UnixNano())
fmt.Println(petname.Generate(*words, *separator))
}
22 changes: 17 additions & 5 deletions petname.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,36 @@ var (

// End word lists

// Call this function once before using any other to get real random results
var localRand *rand.Rand = rand.New(rand.NewSource(1))

// NonDeterministicMode configures the local random generator used internally
// to provide non deterministic results, instead of a pre-defined order that is
// reproducible even after a process restart. If you wish to specify a custom
// contant, call [Seed(int64)].
func NonDeterministicMode() {
rand.Seed(time.Now().UnixNano())
localRand.Seed(time.Now().UnixNano())
}

// Seed configures the local random generator, allowing you to specify a
// constant for reproducible "randomness" or provide a custom value for
// "true" randomness.
func Seed(seed int64) {
localRand.Seed(seed)
}

// Adverb returns a random adverb from a list of petname adverbs.
func Adverb() string {
return adverbs[rand.Intn(len(adverbs))]
return adverbs[localRand.Intn(len(adverbs))]
}

// Adjective returns a random adjective from a list of petname adjectives.
func Adjective() string {
return adjectives[rand.Intn(len(adjectives))]
return adjectives[localRand.Intn(len(adjectives))]
}

// Name returns a random name from a list of petname names.
func Name() string {
return names[rand.Intn(len(names))]
return names[localRand.Intn(len(names))]
}

// Generate generates and returns a random pet name.
Expand Down

0 comments on commit 64ecdb6

Please sign in to comment.