次のようなコードがあります。
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を生成するより良い方法はありますか?
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
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)。
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を作成する新しい一般的なメソッドがあります。
「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
}
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に準拠しています
gofrs/uuid は satori/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())
ラスコックスの 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
のみがプレイグラウンドですべてゼロを返します。ローカルで正常に動作するはずです。
同じスレッドで、他のメソッド/参照/パッケージがいくつか見つかりました。
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
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
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)
}
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
このライブラリは、uuidの生成と解析の標準です。