Есть ли метод для создания UUID с языком go

у меня есть код, который выглядит так:

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].

есть ли лучший способ генерации UUIDs?

12 ответов


u[8] = (u[8] | 0x80) & 0xBF // what's the purpose ?
u[6] = (u[6] | 0x40) & 0x4F // what's 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

вы можете генерировать UUID с помощью перейти-идентификатор UUID библиотека. Это можно установить с помощью:

go get github.com/nu7hatch/gouuid

вы можете генерировать случайные (версия 4) UUID с:

import "github.com/nu7hatch/gouuid"

...

u, err := uuid.NewV4()

возвращенный UUID type представляет собой 16-байтовый массив, поэтому вы можете легко получить двоичное значение. Он также предоставляет стандартное представление шестнадцатеричной строки через его String() метод.

код, который у вас есть, также выглядит так, как будто он также будет генерировать действительную версию 4 UUID: побитовое манипуляции, которые вы выполняете в конце, устанавливают поля версии и варианта UUID правильно определите его как версию 4. Это делается для отличия случайных UUID от тех, которые генерируются с помощью других алгоритмов (например, версия 1 UUID на основе вашего MAC-адреса и времени).


на 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 на основе существующих данных.


"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
}

gofrs / uuid - это замена Сатори/идти.идентификатор UUID, который является самый звездный пакет UUID для Go. Оно поддерживает версии 1-5 UUID и RFC 4122 и DCE 1.1 уступчивое.

import "github.com/gofrs/uuid"

// Create a Version 4 UUID, panicking on error
u := uuid.Must(uuid.NewV4())

от Расса Кокса в должности:

официальной библиотеки нет. Игнорирование ошибок, это похоже на то, что это будет работать нормально:

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 возвращает все нули на детской площадке. Должен работать нормально локально.

в том же потоке есть некоторые другие найдены методы / ссылки/пакеты.


как часть спецификации uuid, если вы генерируете uuid из случайного, он должен содержать "4 "в качестве 13-го символа и" 8"," 9"," a "или" b " в 17-м (источник).

// this make sure that the 13th character is "4"
u[6] = (u[6] | 0x40) & 0x4F
// this make sure that the 17th is "8", "9", "a", or "b"
u[8] = (u[8] | 0x80) & 0xBF 

на 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)
} 

в 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

официальная реализация Google в настоящее время находится в стадии разработки, но еще не стабильна:https://github.com/google/uuid

похоже, это продолжение https://github.com/pborman/uuid от ответ

создание UUID версии 4 работает следующим образом: uuid, err := uuid.NewRandom()


для 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
}

эта библиотека является нашим стандартом для генерации и анализа uuid:

https://github.com/pborman/uuid