146

次のようなコードがあります。

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 を生成するより良い方法はありますか?

4

12 に答える 12

108

go-uuidライブラリを使用して UUID を生成できます。これは次の方法でインストールできます。

go get github.com/nu7hatch/gouuid

以下を使用して、ランダム (バージョン 4) UUID を生成できます。

import "github.com/nu7hatch/gouuid"

...

u, err := uuid.NewV4()

返さUUIDれる型は 16 バイトの配列であるため、バイナリ値を簡単に取得できます。String()また、そのメソッドを介して標準の 16 進文字列表現も提供します。

あなたが持っているコードは、有効なバージョン 4 UUID も生成するように見えます: 最後に実行するビット単位の操作は、UUID の version および variant フィールドを設定して、バージョン 4 として正しく識別します。これは、ランダムな UUID を他のアルゴリズム (MAC アドレスと時間に基づくバージョン 1 UUID など) によって生成されたものと区別するために行われます。

于 2013-02-28T11:33:48.053 に答える
60

「crypto/rand」は、ランダムバイト生成用のクロスプラットフォーム pkg です。

package main

import (
    "crypto/rand"
    "fmt"
)

// Note - NOT RFC4122 compliant
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
}
于 2014-09-09T03:12:46.023 に答える
32
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
于 2013-02-28T08:36:55.020 に答える
28

gofrs/uuidは、 Go の最もスター付きの UUID パッケージであるsatori/go.uuidの代替です。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())
于 2016-04-25T19:14:13.240 に答える
11

Russ Cox の投稿から:

公式のライブラリはありません。エラーチェックを無視すると、これはうまくいくようです:

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:])

注: 元の Go 1 以前のバージョンでは、最初の行は次のとおりでした。

f, _ := os.Open("/dev/urandom", os.O_RDONLY, 0)

ここでコンパイルして実行/dev/urandomし、プレイグラウンドですべてゼロを返すだけです。ローカルで正常に動作するはずです。

同じスレッドで、他のメソッド/参照/パッケージがいくつか見つかりました。

于 2013-02-28T08:38:32.973 に答える
8

uuid 仕様の一部として、ランダムから uuid を生成する場合、13 番目の文字として「4」を、17 番目の文字として「8」、「9」、「a」、または「b」を含める必要があります ( 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 
于 2015-01-06T05:57:13.230 に答える
4

gorandパッケージには、正規の文字列表現 ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") でバージョン 4 (ランダムに生成された) UUID を返す UUID メソッドがあり、RFC 4122 に準拠しています

また、crypto/rand パッケージを使用して、Go がサポートするすべてのプラットフォームで最も暗号的に安全な UUID の生成を保証します。

import "github.com/leonelquinteros/gorand"

func main() {
    uuid, err := gorand.UUID()
    if err != nil {
        panic(err.Error())
    }

    println(uuid)
} 
于 2016-06-15T00:00:39.450 に答える
1

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
}
于 2013-02-28T09:22:57.227 に答える
1

このライブラリは、uuid の生成と解析の標準です。

https://github.com/pborman/uuid

于 2015-08-14T18:10:39.003 に答える