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

har*_*ass 96 uuid go

我的代码看起来像这样:

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)
Run Code Online (Sandbox Code Playgroud)

它返回一个长度为32的字符串,但我不认为它是一个有效的UUID.如果它是一个真正的UUID,为什么它是一个UUID,什么是修改的值的代码的目的u[8]u[6].

有没有更好的方法来生成UUID?

Jam*_*dge 92

您可以使用go-uuid库生成UUID .这可以安装:

go get github.com/nu7hatch/gouuid
Run Code Online (Sandbox Code Playgroud)

您可以使用以下命令生成随机(版本4)UUID:

import "github.com/nu7hatch/gouuid"

...

u, err := uuid.NewV4()
Run Code Online (Sandbox Code Playgroud)

返回的UUID类型是一个16字节的数组,因此您可以轻松地检索二进制值.它还通过其String()方法提供标准的十六进制字符串表示.

你看到的代码也会生成一个有效的版本4 UUID:你在最后执行的按位操作设置UUID的版本和变量字段,以正确地将其标识为版本4.这样做是为了区分随机UUID和通过其他算法生成的UUID(例如,基于您的MAC地址和时间的版本1 UUID).

  • @ErikAigner只要它是50行我就不用考虑,编写和测试,我会带他们谢谢你.我还有其他的东西要做,然后重新发明轮子. (29认同)
  • @ErikAigner 重新发明轮子也有点不必要。如果一个图书馆存在并且做得很好,为什么要自己做而不是为了学习如何去做。 (3认同)
  • @Flimzy对于不知道自己在做什么的人来说很可能是真的。引入不必要的依赖关系总是一件坏事。 (2认同)
  • 该库看起来实际上不符合RFC4122:https://github.com/nu7hatch/gouuid/issues/28(截至2016年1月1日,当前未解决的问题) (2认同)
  • @ErikAigner我发现那个有点不可思议.没有人重新发明已经完成的东西,除非你能做得更好或需要特定于你的程序的东西,如果你检查代码并看到它做得好为什么麻烦自己做 - 不仅浪费开发时间和成本,你也是如果你不完全知道自己在做什么,可能会带来错误或者只是错误的实现,这些库通常会成为知道自己在做什么的人.使用第三方库并不是新手,它唯一的新手只是假设它有效而不是先检查代码. (2认同)

twi*_*inj 69

go-uuid库不符合RFC4122.变量位未正确设置.社区成员已经多次尝试将此修复,但是不接受对修复的拉取请求.

您可以使用我根据库重写的Go uuid库生成UUID go-uuid.有几个修复和改进.这可以安装:

go get github.com/twinj/uuid
Run Code Online (Sandbox Code Playgroud)

您可以使用以下命令生成随机(版本4)UUID:

import "github.com/twinj/uuid"

u := uuid.NewV4()
Run Code Online (Sandbox Code Playgroud)

返回的UUID类型是接口,底层类型是数组.

该库还会生成v1 UUID并正确生成v3和5个UUID.有几种新方法可以帮助打印和格式化,还有一些新的通用方法可以根据现有数据创建UUID.

  • 我喜欢这个包.我已经正式将它用于我的所有应用程序.我发现nu7hatch包不符合RFC4122. (4认同)
  • 免责声明丢失了吗?:p (4认同)
  • 什么是"下面"的图书馆?你应该避免在SO上面和下面使用,因为它可以很快改变. (2认同)

Ken*_*oud 47

"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
}
Run Code Online (Sandbox Code Playgroud)

  • `pseudo_uuid`,因为它缺少非随机标识符,例如MAC地址以及其他指定的RFC4122吗?因此,它实际上是*更多*随机的。 (3认同)
  • 好答案; 我已经在/sf/answers/3369437431/扩展了它,我认为很多人实际上不需要专门使用UUID(也不是我认为我需要使用的sha1/sha256)我自己的随机问题),但只是想要一些随机和独特的东西,你的样本为解决方案提供了良好的开端 (2认同)

stw*_*ykd 40

您应该使用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())
}
Run Code Online (Sandbox Code Playgroud)

该软件包符合RFC4122和DCE 1.1

  • 我认为这个答案应该是最重要的,因为这似乎是当前最正确的解决方案。接受的答案没有最多的支持,最高的2个支持的答案提到的软件包可能不如google / uuid更好 (7认同)
  • 注意,uuid.NewUUID()是基于时钟的“ version1”。对于基于加密随机数(https://golang.org/pkg/crypto/rand/)的“ version4”,请使用uuid.NewRandom()。 (3认同)

jim*_*imt 27

u[8] = (u[8] | 0x80) & 0xBF // what's the purpose ?
u[6] = (u[6] | 0x40) & 0x4F // what's the purpose ?
Run Code Online (Sandbox Code Playgroud)

这些行将字节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)
}
Run Code Online (Sandbox Code Playgroud)

产量:

$ go run uuid.go 
dc9076e9-2fda-4019-bd2c-900a8284b9c4
Run Code Online (Sandbox Code Playgroud)

  • 调用可能存在或可能不存在的外部程序是执行此相当简单的任务的可怕方法. (34认同)
  • 值得注意的是,这种方法很慢; 在2012年的MacBook Air上,这种策略只能生产170 uuids /秒. (21认同)
  • 使用nu7hatch/gouuid库,我能够生成172,488 uuids /秒. (10认同)
  • 在我的系统(Ubuntu 15.10)上我还需要通过strings.Trim(string(out))运行命令输出来删除换行符,否则它被输入为尾随?文件系统中的字符. (3认同)
  • 很好地解释了“ u [6]”和“ u [8]”字节。 (2认同)

bma*_*pin 23

gofrs/UUID是更换为顿悟/ go.uuid,这是最出演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())
Run Code Online (Sandbox Code Playgroud)


shu*_*fan 17

谷歌的官方实施目前正在开发中,但还不稳定:https://github.com/google/uuid

看起来这是来自这个答案https://github.com/pborman/uuid的延续

生成版本4 UUID的工作方式如下: __CODE__

更新:版本1.0.0已发布,有关可能不稳定的说明已被删除.

  • [godoc](https://godoc.org/github.com/google/uuid#New) 推荐使用 `New()`,它等价于 `uuid.Must(uuid.NewRandom())` (3认同)
  • 请注意,New() 可能“致命”(在某些情况下这是可以的)。如果您不希望程序致命,只需使用 uuid.NewRandom() - 它会返回 UUID 和错误。 (3认同)
  • 有一个“NewString”。NewString 等价于表达式 `uuid.New().String()` (3认同)

zzz*_*zzz 13

来自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:])
Run Code Online (Sandbox Code Playgroud)

注意:在原版的Go 1版本中,第一行是:

f, _ := os.Open("/dev/urandom", os.O_RDONLY, 0)
Run Code Online (Sandbox Code Playgroud)

在这里编译并执行,只/dev/urandom返回操场中的所有零.应该在当地工作正常.

在同一个线程中,还有一些其他方法/引用/包.

  • 这虽然不会产生有效的UUID:第4点的UUID(基于随机数据类型)需要几个位以一定的方式,以避免与非随机UUID格式冲突的设置. (10认同)
  • 在我看来最好使用`import"crypto/rand",但是对于`uuid:= fmt.Sprintf("%x-%x-%x-%x-%x",b [0:4] ,b [4:6],b [6:8],b [8:10],b [10:])`.结合OP的代码,这很有效. (4认同)
  • 使用crypto / rand软件包:http://play.golang.org/p/7JJDx4GL77。zzzz的代码执行crypt / rand的操作,除了它还涵盖了不支持/ dev / urandom的平台(Windows)。 (2认同)
  • @Matt:问题在于,其他UUID格式通过委派给其他权威机构(例如,您的以太网MAC地址是唯一的)来获得其唯一性,然后将其与其他内容(例如时间和计数器)组合在一起。如果生成的随机UUID格式未正确设置为V4,则会削弱系统性能。 (2认同)

小智 12

使用来自 google 的包随机 UUID:

package main

import (
    "fmt"

    "github.com/google/uuid"
)

func main() {
    out := uuid.Must(uuid.NewRandom()).String()
    fmt.Println(out)
}
Run Code Online (Sandbox Code Playgroud)

输出:

a1c11a53-c4be-488f-89b6-f83bf2d48dab
Run Code Online (Sandbox Code Playgroud)


eri*_*ang 7

作为uuid规范的一部分,如果你从随机生成一个uuid,它必须包含一个"4"作为第13个字符和一个"8","9","a"或"b"在17().

// 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 
Run Code Online (Sandbox Code Playgroud)


sou*_*ake 5

在 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))
}
Run Code Online (Sandbox Code Playgroud)

没有外部依赖!

$ go run uuid.go 
3ee995e3-0c96-4e30-ac1e-f7f04fd03e44
Run Code Online (Sandbox Code Playgroud)

  • 被否决是因为在用于多平台应用程序的编程语言中直接依赖主机平台比外部依赖更糟糕。 (6认同)
  • 编程语言可以是多平台的,但它是 Linux 特定的非常常见的解决方案,永远不会在其他平台上使用,因此,在我看来,这是一个有效的响应。 (2认同)