web-dev-qa-db-ja.com

go言語でUUIDを生成する方法はありますか

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

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

88
hardPass
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
27
jimt

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のバージョンフィールドとバリアントフィールドが正しく設定されます バージョン4として識別 。これは、ランダムなUUIDを他のアルゴリズムで生成されたものと区別するために行われます(たとえば、MACアドレスと時間に基づいたバージョン1 UUID)。

88

go-uuidライブラリはRFC4122に準拠していません。バリアントビットが正しく設定されていません。コミュニティのメンバーはこれを修正しようと試みましたが、修正のプルリクエストは受け付けられていません。

go-uuidライブラリに基づいて書き直したGo uuidライブラリを使用してUUIDを生成できます。いくつかの修正と改善があります。これは次のものでインストールできます。

go get github.com/twinj/uuid

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

import "github.com/twinj/uuid"

u := uuid.NewV4()

返されるUUIDタイプはインターフェースであり、基礎となるタイプは配列です。

また、ライブラリはv1 UUIDを生成し、v3および5 UUIDを正しく生成します。印刷とフォーマットを支援するいくつかの新しいメソッドと、既存のデータに基づいてUUIDを作成する新しい一般的なメソッドがあります。

69
twinj

「crypto/Rand」は、ランダムバイトジェネレーター用のクロスプラットフォームパッケージです。

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
}
47
Ken Cloud

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に準拠しています

27
stwykd

gofrs/uuidsatori/go.uuid の代わりになります。これは 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())
22
bmaupin

ラスコックスの 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:])

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

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

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

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

13
zzzz

Googleによる公式の実装があります: https://github.com/google/uuid

バージョン4 UUIDの生成は次のように機能します。

package main

import (
    "fmt"
    "github.com/google/uuid"
)

func main() {
    id := uuid.New()
    fmt.Println(id.String())
}

ここで試してください: https://play.golang.org/p/6YPi1djUMj9

12
shutefan

Uuid仕様の一部として、ランダムからuuidを生成する場合、13番目の文字として「4」、17番目に「8」、「9」、「a」、または「b」を含める必要があります(- ソース )。

// 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 
7
eric chiang

gorand パッケージには、標準の文字列表現( "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx")でバージョン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)
} 
4
peiiion

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
1
soulshake

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

https://github.com/pborman/uuid

0
James McGill