有没有一种方法可以用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的string,但我不认为它是一个有效的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上,你可以select调用/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() 

返回的UUIDtypes是一个16字节的数组,因此您可以轻松检索二进制值。 它还通过其String()方法提供标准的hexstring表示。

你也看起来像这样的代码也会生成一个有效的版本4 UUID:你在最后执行的按位操作设置UUID的版本和变体字段,以正确识别它为版本4 。 这样做是为了区分随机的UUID和通过其他algorithm生成的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() 

返回的UUIDtypes是一个接口,底层types是一个数组。

该库还生成v1 UUID并正确生成v3和5 UUID。 有几种新的方法可以帮助打印和格式化,还有一些基于现有数据创buildUUID的新的一般方法。

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

从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返回操场中的所有零。 应该在当地正常工作。

在同一个线程中还有一些其他的方法/引用/包发现。

FWIW, satori / go.uuid是Go最 出色的UUID软件包 。 它支持UUID版本1-5,符合RFC 4122和DCE 1.1。

 import "github.com/satori/go.uuid" u := uuid.NewV4() 

作为uuid规范的一部分,如果从随机生成一个uuid,它必须包含第十三个字符“4”和第十七个( 源 )中的“8”,“9”,“a”或“b”。

 // 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方法,它以规范的string表示forms(“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”)返回版本4(随机生成的)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) } 

对于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 } 

在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生成和parsing标准:

https://github.com/pborman/uuid