有没有一种方法可以用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()
返回的UUID
types是一个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标准: