Je ne comprends pas pourquoi les gens font des semis avec une valeur temporelle. D'après mon expérience, cela n'a jamais été une bonne idée. Par exemple, alors que l'horloge du système est peut-être représentée en nanosecondes, la précision de l'horloge du système n'est pas en nanosecondes.
Ce programme ne doit pas être exécuté sur le terrain de jeu Go mais si vous l'exécutez sur votre machine, vous obtiendrez une estimation approximative du type de précision que vous pouvez attendre. Je vois des incréments d'environ 1000000 ns, donc des incréments de 1 ms. Cela représente 20 bits d'entropie qui ne sont pas utilisés. Pendant ce temps, les bits élevés sont généralement constants ! En gros, ~24 bits d'entropie sur une journée, ce qui est très facile à forcer (ce qui peut créer des vulnérabilités).
Le degré d'importance que vous accordez à cet aspect variera, mais vous pouvez éviter les pièges des valeurs de semences basées sur l'horloge en utilisant simplement l'attribut crypto/rand.Read
comme source pour votre semence. Il vous donnera cette qualité non déterministe que vous recherchez probablement dans vos nombres aléatoires (même si l'implémentation réelle elle-même est limitée à un ensemble de séquences aléatoires distinctes et déterministes).
import (
crypto_rand "crypto/rand"
"encoding/binary"
math_rand "math/rand"
)
func init() {
var b [8]byte
_, err := crypto_rand.Read(b[:])
if err != nil {
panic("cannot seed math/rand package with cryptographically secure random number generator")
}
math_rand.Seed(int64(binary.LittleEndian.Uint64(b[:])))
}
En passant, mais en relation avec votre question. Vous pouvez créer votre propre rand.Source
en utilisant cette méthode pour éviter le coût des verrous protégeant la source. Le site rand
Les fonctions utilitaires des paquets sont pratiques mais elles utilisent également des verrous sous le capot pour empêcher l'utilisation simultanée de la source. Si vous n'avez pas besoin de cela, vous pouvez l'éviter en créant votre propre fichier Source
et de l'utiliser de manière non-concurrente. Quoi qu'il en soit, vous ne devez PAS réensemencer votre générateur de nombres aléatoires entre les itérations, il n'a jamais été conçu pour être utilisé de cette façon.
Edit : J'ai travaillé dans l'ITAM/SAM et le client que nous avons construit (à l'époque) utilisait un semis basé sur une horloge. Après une mise à jour de Windows, de nombreuses machines du parc de l'entreprise ont redémarré à peu près au même moment. Cela a provoqué une attaque DoS involontaire sur l'infrastructure des serveurs en amont, car le client utilisait le temps de démarrage du système pour semer l'aléatoire et ces machines ont fini par choisir plus ou moins aléatoirement le même créneau horaire pour faire leur rapport. Ils étaient censés répartir la charge sur une période d'environ une heure, mais cela ne s'est pas produit. Seed responsbily !
2 votes
Le "if string(randInt(65,90))!=temp {" ressemble à une tentative d'ajouter une sécurité supplémentaire, mais les choses se ressemblent les unes après les autres par hasard. En faisant cela, vous pouvez en fait diminuer l'entropie.
3 votes
Par ailleurs, il n'est pas nécessaire de convertir en UTC dans "time.Now().UTC().UnixNano()". Le temps Unix est calculé depuis Epoch qui est UTC de toute façon.
2 votes
Vous devez définir la graine une fois, une seule fois, et jamais plus d'une fois. Si votre application fonctionne pendant plusieurs jours, vous pouvez la définir une fois par jour.
0 votes
Vous devez semer une fois. Et je pense que "Z" peut ne jamais apparaître, je suppose ? Je préfère donc utiliser l'index de début inclusif et l'index de fin exclusif.