我的代码如下:
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?
答案 0 :(得分:85)
您可以使用go-uuid库生成UUID。这可以安装:
go get github.com/nu7hatch/gouuid
您可以使用以下内容生成随机(版本4)UUID
import "github.com/nu7hatch/gouuid"
...
u, err := uuid.NewV4()
返回的UUID
类型是一个16字节的数组,因此您可以轻松地检索二进制值。它还通过其String()
方法提供标准十六进制字符串表示。
您所看到的代码也会生成有效的版本4 UUID:您在最后执行的按位操作会将UUID的版本和变量字段设置为正确identify it as version 4。这样做是为了区分随机UUID和通过其他算法生成的UUID(例如,基于您的MAC地址和时间的版本1 UUID)。
答案 1 :(得分:68)
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的新方法。
答案 2 :(得分:46)
"加密/兰特#34;是用于随机字节生成的跨平台包
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
}
答案 3 :(得分:26)
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
答案 4 :(得分:21)
gofrs/uuid替代satori/go.uuid,即most starred UUID package for Go。它支持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())
答案 5 :(得分:13)
来自Russ Cox的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)
Here它编译并执行,只有/dev/urandom
返回操场上的全部零。应该在当地工作正常。
在同一个线程中,找到了一些其他方法/引用/包。
答案 6 :(得分:9)
Google的官方实施目前正在开发但尚未稳定:https://github.com/google/uuid
看起来它是https://github.com/pborman/uuid的this answer的延续
生成版本4 UUID的工作方式如下:
uuid := uuid.New()
更新: 版本1.0.0已经发布,关于可能的不稳定性的说明已被删除。
答案 7 :(得分:7)
作为uuid规范的一部分,如果你从随机生成一个uuid,它必须包含一个“4”作为第13个字符和一个“8”,“9”,“a”或“b”在17( 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
答案 8 :(得分:7)
您应该使用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
答案 9 :(得分:4)
gorand包具有UUID方法,该方法以其规范字符串表示形式返回版本4(随机生成的)UUID(“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”),并且符合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)
}
答案 10 :(得分:2)
在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
答案 11 :(得分:0)
这个库是我们生成和解析的标准:
答案 12 :(得分:-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
}