У меня есть код, который выглядит так:
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)
Он возвращает строку длиной 32, но я не думаю, что это действительный UUID. Если это реальный UUID, то почему он является UUID, и какова цель кода, который изменяет значение u[8]
и u[6]
.
Есть ли лучший способ генерации UUID?
Ответ 1
u[8] = (u[8] | 0x80) & 0xBF // what the purpose ?
u[6] = (u[6] | 0x40) & 0x4F // what the purpose ?
Эти строки фиксируют значения байтов 6 и 8 в определенном диапазоне. rand.Read
возвращает случайные байты в диапазоне 0-255
, которые не являются допустимыми значениями для UUID. Насколько я могу судить, это должно быть сделано для всех значений в срезе, хотя.
Если вы используете linux, вы также можете вызвать /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)
}
Что дает:
$ go run uuid.go
dc9076e9-2fda-4019-bd2c-900a8284b9c4
Ответ 2
Вы можете сгенерировать UUID, используя библиотеку go-uuid. Это можно установить с помощью
go get github.com/nu7hatch/gouuid
Вы можете генерировать случайные (версии 4) UUID с помощью:
import "github.com/nu7hatch/gouuid"
...
u, err := uuid.NewV4()
Возвращаемый тип UUID
- это 16-байтовый массив, поэтому вы можете легко получить двоичное значение. Он также предоставляет стандартное шестнадцатеричное представление через метод String()
.
Код, который у вас также выглядит, также будет генерировать допустимую версию 4 UUID: побитовое манипулирование, которое вы выполняете в конце, правильно установило версии и вариантные поля UUID идентифицирует его как версию 4. Это делается для того, чтобы отличать случайные UUID от тех, которые генерируются с помощью других алгоритмов (например, UUID версии 1 на основе вашего MAC-адреса и времени).
Ответ 3
Библиотека go-uuid
НЕ соответствует RFC4122. Вариантные биты установлены неправильно. Было несколько попыток членов сообщества получить это исправление, но запросы на получение исправления не принимаются.
Вы можете сгенерировать UUID, используя библиотеку Go uuid, которую я переписал на основе библиотеки go-uuid
. Есть несколько исправлений и улучшений. Это можно установить с помощью
go get github.com/twinj/uuid
Вы можете генерировать случайные (версии 4) UUID с помощью:
import "github.com/twinj/uuid"
u := uuid.NewV4()
Возвращенный тип UUID - это интерфейс, а базовый тип - это массив.
Библиотека также генерирует v1 UUID и правильно генерирует v3 и 5 UUID. Существует несколько новых методов, помогающих в печати и форматировании, а также новые общие методы создания UUID на основе существующих данных.
Ответ 4
"crypto/rand" - это кросс-платформа pkg для генерации случайных байтов
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
}
Ответ 5
Вы должны использовать 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())
}
Этот пакет соответствует RFC4122 и DCE 1.1
Ответ 6
gofrs/uuid - это замена satori/go.uuid, который является самым популярным UUID-пакетом для Go. Он поддерживает UUID версии 1-5 и совместим с RFC 4122 и DCE 1.1.
import "github.com/gofrs/uuid"
// Create a Version 4 UUID, panicking on error
u := uuid.Must(uuid.NewV4())
Ответ 7
Существует официальная реализация от Google: https://github.com/google/uuid
Генерация UUID версии 4 работает следующим образом:
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id := uuid.New()
fmt.Println(id.String())
}
Попробуйте здесь: https://play.golang.org/p/6YPi1djUMj9
Ответ 8
Из Russ Cox post:
Там нет официальной библиотеки. Игнорируя проверку ошибок, похоже, что это будет нормально работать:
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:])
Примечание. В исходной версии Pre Go 1 первая строка была:
f, _ := os.Open("/dev/urandom", os.O_RDONLY, 0)
Здесь он компилируется и исполняется, только /dev/urandom
возвращает все нули на игровой площадке. Должен работать нормально локально.
В том же потоке найдены некоторые другие методы/ссылки/пакеты.
Ответ 9
Как часть спецификации uuid, если вы создаете uuid из случайного, он должен содержать "4" в качестве 13-го символа и "8", "9", "a" или "b" в 17-м (источник).
// 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
Ответ 10
Пакет gorand имеет метод UUID, который возвращает произвольный UUID версии 4 (случайно генерируемый) в его каноническом представлении строки ( "xxxxxxxx- xxxx-xxxx-xxxx-xxxxxxxxxxxx" ) и совместим с RFC 4122.
Он также использует пакет crypto/rand для обеспечения наиболее криптографически безопасного поколения UUID на всех платформах, поддерживаемых Go.
import "github.com/leonelquinteros/gorand"
func main() {
uuid, err := gorand.UUID()
if err != nil {
panic(err.Error())
}
println(uuid)
}
Ответ 11
В Linux вы можете читать из /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))
}
Нет внешних зависимостей!
$ go run uuid.go
3ee995e3-0c96-4e30-ac1e-f7f04fd03e44
Ответ 12
В Windows я недавно сделал это:
// +build windows
package main
import (
"syscall"
"unsafe"
)
var (
modrpcrt4 = syscall.NewLazyDLL("rpcrt4.dll")
procUuidCreate = modrpcrt4.NewProc("UuidCreate")
)
const (
RPC_S_OK = 0
)
func NewUuid() ([]byte, error) {
var uuid [16]byte
rc, _, e := syscall.Syscall(procUuidCreate.Addr(), 1,
uintptr(unsafe.Pointer(&uuid[0])), 0, 0)
if int(rc) != RPC_S_OK {
if e != 0 {
return nil, error(e)
} else {
return nil, syscall.EINVAL
}
}
return uuid[:], nil
}
Ответ 13
Эта библиотека является нашим стандартом для генерации и анализа uuid:
https://github.com/pborman/uuid