J'ai un code qui ressemble à ceci:
u := make([]byte, 16)
_, err := Rand.Read(u)
if err != nil {
return
}
u[8] = (u[8] | 0x80) & 0xBF // what does this do?
u[6] = (u[6] | 0x40) & 0x4F // what does this do?
return hex.EncodeToString(u)
Il renvoie une chaîne d'une longueur de 32, mais je ne pense pas que ce soit un UUID valide. S'il s'agit d'un UUID réel, pourquoi s'agit-il d'un UUID et quel est l'objectif du code qui modifie la valeur de u[8]
et u[6]
.
Existe-t-il un meilleur moyen de générer des UUID?
u[8] = (u[8] | 0x80) & 0xBF // what's the purpose ?
u[6] = (u[6] | 0x40) & 0x4F // what's the purpose ?
Ces lignes fixent les valeurs des octets 6 et 8 à une plage spécifique. Rand.Read
renvoie des octets aléatoires dans la plage 0-255
, qui ne sont pas toutes des valeurs valides pour un UUID. Autant que je sache, cela devrait cependant être fait pour toutes les valeurs de la tranche.
Si vous êtes sur Linux, vous pouvez aussi appeler /usr/bin/uuidgen
.
package main
import (
"fmt"
"log"
"os/exec"
)
func main() {
out, err := exec.Command("uuidgen").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", out)
}
Quels rendements:
$ go run uuid.go
dc9076e9-2fda-4019-bd2c-900a8284b9c4
Vous pouvez générer des UUID à l'aide de la bibliothèque go-uuid . Ceci peut être installé avec:
go get github.com/nu7hatch/gouuid
Vous pouvez générer des UUID aléatoires (version 4) avec:
import "github.com/nu7hatch/gouuid"
...
u, err := uuid.NewV4()
Le type UUID
renvoyé est un tableau de 16 octets. Vous pouvez ainsi extraire facilement la valeur binaire. Il fournit également la représentation standard des chaînes hexadécimales via sa méthode String()
.
Le code que vous avez semble également générer une UUID valide pour la version 4: la manipulation binaire effectuée à la fin définit correctement les champs de version et de variante de l'UUID l'identifie comme version 4 . Ceci est fait pour distinguer les UUID aléatoires de ceux générés via d’autres algorithmes (par exemple, des UUID de version 1 basés sur votre adresse MAC et votre heure).
La bibliothèque go-uuid
N'est PAS conforme à RFC4122. Les bits de variante ne sont pas définis correctement. Des membres de la communauté ont tenté à plusieurs reprises de corriger ce problème, mais les demandes d'extraction du correctif ne sont pas acceptées.
Vous pouvez générer des UUID à l'aide de la bibliothèque Go uuid que j'ai récrite en fonction de la bibliothèque go-uuid
. Il existe plusieurs correctifs et améliorations. Ceci peut être installé avec:
go get github.com/twinj/uuid
Vous pouvez générer des UUID aléatoires (version 4) avec:
import "github.com/twinj/uuid"
u := uuid.NewV4()
Le type UUID renvoyé est une interface et le type sous-jacent est un tableau.
La bibliothèque génère également des UUID v1 et génère correctement les vU et 5 UUID. Il existe plusieurs nouvelles méthodes d'aide à l'impression et au formatage, ainsi que de nouvelles méthodes générales pour créer des UUID basés sur des données existantes.
"crypto/Rand" est un paquet multiplateforme pour le générateur d'octets aléatoires
package main
import (
"crypto/Rand"
"fmt"
)
func pseudo_uuid() (uuid string) {
b := make([]byte, 16)
_, err := Rand.Read(b)
if err != nil {
fmt.Println("Error: ", err)
return
}
uuid = fmt.Sprintf("%X-%X-%X-%X-%X", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
return
}
Vous devez utiliser google/uuid https://github.com/google/uuid
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id, err := uuid.NewUUID()
if err !=nil {
// handle error
}
fmt.Printf(id.String())
}
Ce paquet est conforme aux normes RFC4122 et DCE 1.1
gofrs/uuid est le remplacement de satori/go.uuid , qui est le le paquet UUID le plus étoilé pour Go . Il prend en charge les versions UUID 1 à 5 et est conforme aux normes RFC 4122 et DCE 1.1.
import "github.com/gofrs/uuid"
// Create a Version 4 UUID, panicking on error
u := uuid.Must(uuid.NewV4())
De Russ Cox's post :
Il n'y a pas de bibliothèque officielle. En ignorant les erreurs, cela semble fonctionner correctement:
f, _ := os.Open("/dev/urandom")
b := make([]byte, 16)
f.Read(b)
f.Close()
uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
Remarque: dans la version originale, avant Go 1, la première ligne était la suivante:
f, _ := os.Open("/dev/urandom", os.O_RDONLY, 0)
Ici il compile et exécute, seulement /dev/urandom
renvoie tous les zéros dans la cour de récréation. Devrait bien fonctionner localement.
Dans le même fil, d'autres méthodes/références/packages ont été trouvés.
Il existe une implémentation officielle par Google: https://github.com/google/uuid
La génération d'un UUID version 4 fonctionne comme suit:
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id := uuid.New()
fmt.Println(id.String())
}
Essayez-le ici: https://play.golang.org/p/6YPi1djUMj9
Dans le cadre de la spécification uuid, si vous générez un uuid à partir d’aléatoire, il doit contenir un "4" comme 13ème caractère et un "8", "9", "a" ou "b" dans le 17ème ( source ).
// this makes sure that the 13th character is "4"
u[6] = (u[6] | 0x40) & 0x4F
// this makes sure that the 17th is "8", "9", "a", or "b"
u[8] = (u[8] | 0x80) & 0xBF
Le package gorand a une méthode UUID qui renvoie un UUID version 4 (généré aléatoirement) dans sa représentation sous forme de chaîne canonique ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") et sa conformité à la norme RFC 4122.
Il utilise également le package crypto/Rand pour garantir la génération la plus sécurisée d’UUID sur toutes les plates-formes prises en charge par Go.
import "github.com/leonelquinteros/gorand"
func main() {
uuid, err := gorand.UUID()
if err != nil {
panic(err.Error())
}
println(uuid)
}
Sous Linux, vous pouvez lire à partir de /proc/sys/kernel/random/uuid
:
package main
import "io/ioutil"
import "fmt"
func main() {
u, _ := ioutil.ReadFile("/proc/sys/kernel/random/uuid")
fmt.Println(string(u))
}
Aucune dépendance externe!
$ go run uuid.go
3ee995e3-0c96-4e30-ac1e-f7f04fd03e44
Cette bibliothèque est notre standard pour la génération et l'analyse uuid: