有没有一种方法可以使用go语言生成UUID

时间:2013-02-28 07:58:39

标签: 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?

13 个答案:

答案 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/uuidthis 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)

这个库是我们生成和解析的标准:

https://github.com/pborman/uuid

答案 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
}