英文:
Is there a method to generate a UUID with Go language?
问题
我有一段代码看起来像这样:
u := make([]byte, 16)
_, err := rand.Read(u)
if err != nil {
return
}
u[8] = (u[8] | 0x80) & 0xBF // 这段代码是做什么的?
u[6] = (u[6] | 0x40) & 0x4F // 这段代码是做什么的?
return hex.EncodeToString(u)
它返回一个长度为32的字符串,但我不认为它是一个有效的UUID。如果它是一个真正的UUID,为什么它是一个UUID,以及修改u[8]
和u[6]
值的代码的目的是什么?
有没有更好的方法来生成UUID?
英文:
I have code that looks like this:
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)
It returns a string with a length of 32, but I don't think it is a valid UUID. If it is a real UUID, why is it a UUID, and what is the purpose of the code that modifies the value of u[8]
and u[6]
?
Is there a better way of generating UUIDs?
答案1
得分: 197
这里有一个由Google官方提供的实现:https://github.com/google/uuid
生成版本4的UUID的方法如下:
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id := uuid.New()
fmt.Println(id.String())
}
在这里尝试一下:https://play.golang.org/p/6YPi1djUMj9
英文:
There is an official implementation by Google: https://github.com/google/uuid
Generating a version 4 UUID works like this:
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id := uuid.New()
fmt.Println(id.String())
}
Try it here: https://play.golang.org/p/6YPi1djUMj9
答案2
得分: 114
你可以使用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的版本和变体字段设置为正确地标识其为版本4。这样做是为了区分随机UUID和通过其他算法生成的UUID(例如基于你的MAC地址和时间的版本1 UUID)。
英文:
You can generate UUIDs using the go-uuid library. This can be installed with:
go get github.com/nu7hatch/gouuid
You can generate random (version 4) UUIDs with:
import "github.com/nu7hatch/gouuid"
...
u, err := uuid.NewV4()
The returned UUID
type is a 16 byte array, so you can retrieve the binary value easily. It also provides the standard hex string representation via its String()
method.
The code you have also looks like it will also generate a valid version 4 UUID: the bitwise manipulation you perform at the end set the version and variant fields of the UUID to correctly identify it as version 4. This is done to distinguish random UUIDs from ones generated via other algorithms (e.g. version 1 UUIDs based on your MAC address and time).
答案3
得分: 78
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和v5 UUID。还有几个新的方法可用于打印和格式化,以及基于现有数据创建UUID的新通用方法。
英文:
The go-uuid
library is NOT RFC4122 compliant. The variant bits are not set correctly. There have been several attempts by community members to have this fixed but pull requests for the fix are not being accepted.
You can generate UUIDs using the Go uuid library I rewrote based on the go-uuid
library. There are several fixes and improvements. This can be installed with:
go get github.com/twinj/uuid
You can generate random (version 4) UUIDs with:
import "github.com/twinj/uuid"
u := uuid.NewV4()
The returned UUID type is an interface and the underlying type is an array.
The library also generates v1 UUIDs and correctly generates v3 and 5 UUIDs. There are several new methods to help with printing and formatting and also new general methods to create UUIDs based off of existing data.
答案4
得分: 61
"crypto/rand"是一个用于生成随机字节的跨平台包
package main
import (
"crypto/rand"
"fmt"
)
// 注意 - 不符合RFC4122标准
func pseudo_uuid() (uuid string) {
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
fmt.Println("错误: ", 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
}
英文:
"crypto/rand" is cross platform pkg for random bytes generattion
package main
import (
"crypto/rand"
"fmt"
)
// Note - NOT RFC4122 compliant
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
}
答案5
得分: 34
u[8] = (u[8] | 0x80) & 0xBF // 这是什么目的?
u[6] = (u[6] | 0x40) & 0x4F // 这是什么目的?
这些代码行将字节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
英文:
u[8] = (u[8] | 0x80) & 0xBF // what's the purpose ?
u[6] = (u[6] | 0x40) & 0x4F // what's the purpose ?
These lines clamp the values of byte 6 and 8 to a specific range. rand.Read
returns random bytes in the range 0-255
, which are not all valid values for a UUID. As far as I can tell, this should be done for all the values in the slice though.
If you are on linux, you can alternatively call /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)
}
Which yields:
$ go run uuid.go
dc9076e9-2fda-4019-bd2c-900a8284b9c4
答案6
得分: 32
gofrs/uuid 是 satori/go.uuid 的替代品,它是 Go 语言中最受欢迎的 UUID 包,支持 UUID 版本 1-5,并符合 RFC 4122 和 DCE 1.1 标准。
import "github.com/gofrs/uuid"
// 创建一个版本 4 的 UUID,如果出错则会引发 panic
u := uuid.Must(uuid.NewV4())
英文:
gofrs/uuid is the replacement for satori/go.uuid, which is the most starred UUID package for Go. It supports UUID versions 1-5 and is RFC 4122 and DCE 1.1 compliant.
import "github.com/gofrs/uuid"
// Create a Version 4 UUID, panicking on error
u := uuid.Must(uuid.NewV4())
答案7
得分: 12
从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)
这里它可以编译和执行,只是在playground中/dev/urandom
返回全零。在本地应该可以正常工作。
在同一线程中还有一些其他的方法/参考/包。
英文:
From Russ Cox's post:
> There's no official library. Ignoring error checking,
> this seems like it would work fine:
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:])
Note: In the original, pre Go 1 version the first line was:
f, _ := os.Open("/dev/urandom", os.O_RDONLY, 0)
Here it compiles and executes, only /dev/urandom
returns all zeros in the playground. Should work fine locally.
In the same thread there are some other methods/references/packages found.
答案8
得分: 9
使用谷歌的包生成随机UUID:
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
out := uuid.Must(uuid.NewRandom()).String()
fmt.Println(out)
}
输出:
a1c11a53-c4be-488f-89b6-f83bf2d48dab
英文:
Random UUID using package from google:
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
out := uuid.Must(uuid.NewRandom()).String()
fmt.Println(out)
}
Output:
a1c11a53-c4be-488f-89b6-f83bf2d48dab
答案9
得分: 8
作为uuid规范的一部分,如果你从随机生成一个uuid,它必须包含一个"4"作为第13个字符,并且在第17个字符位置上包含一个"8"、"9"、"a"或"b"(来源)。
// 这确保第13个字符是"4"
u[6] = (u[6] | 0x40) & 0x4F
// 这确保第17个字符是"8"、"9"、"a"或"b"
u[8] = (u[8] | 0x80) & 0xBF
英文:
As part of the uuid spec, if you generate a uuid from random it must contain a "4" as the 13th character and a "8", "9", "a", or "b" in the 17th (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
答案10
得分: 7
在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
英文:
On Linux, you can read from /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))
}
No external dependencies!
$ go run uuid.go
3ee995e3-0c96-4e30-ac1e-f7f04fd03e44
答案11
得分: 4
The gorand package has a UUID method that returns a Version 4 (randomly generated) UUID in its canonical string representation ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") and it's RFC 4122 compliant.
It also uses the crypto/rand package to ensure the most cryptographically secure generation of UUIDs across all platforms supported by Go.
import "github.com/leonelquinteros/gorand"
func main() {
uuid, err := gorand.UUID()
if err != nil {
panic(err.Error())
}
println(uuid)
}
英文:
The gorand package has a UUID method that returns a Version 4 (randomly generated) UUID in its canonical string representation ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") and it's RFC 4122 compliant.
It also uses the crypto/rand package to ensure the most cryptographically secure generation of UUIDs across all platforms supported by Go.
import "github.com/leonelquinteros/gorand"
func main() {
uuid, err := gorand.UUID()
if err != nil {
panic(err.Error())
}
println(uuid)
}
答案12
得分: 3
所以你问:<br>
Q1. u[8] = (u[8] | 0x80) & 0xBF // 这是什么意思?<br>
答: 这部分定义了变体。你可以从https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.1了解更多信息。
Q2. u[6] = (u[6] | 0x40) & 0x4F // 这是什么意思?<br>
答: 我们使用最高的4位来表示版本号,所以在这种情况下版本号为4,所以我们想要将其设置为"0100"
。版本4是最常用的UUID版本,它基于随机位生成。它使用128位,其中4位固定用于表示版本号,2位固定用于表示变体
。因此,我们还剩下122位可以随机生成。<br>
你可以通过导入Google的包来生成UUID v4:<br>
https://github.com/google/uuid
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
uuid := uuid.New()
fmt.Println(uuid.String())
}
另外,你也可以尝试我创建的包。它非常轻量且易于理解。https://github.com/bitactro/UUIDv4 <br>
package main
import (
"fmt"
"github.com/bitactro/UUIDv4"
)
func main() {
fmt.Println(uuidv4.GenerateUUID4())
}
英文:
So you asked:<br>
Q1. u[8] = (u[8] | 0x80) & 0xBF // what does this do?<br>
Ans: This section defines variant. You can learn more about it from https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.1
Q2. u[6] = (u[6] | 0x40) & 0x4F // what does this do?<br>
Ans: We show version number with the most 4 significant bits so in this case version 4 so we want to set it with "0100"
. Version 4 is most widely used UUID and its based on random bits generation. It uses 128 bits, Out of which 4 bits are fixed to tell version number and 2 bits are fixed to tell variant
. So we have 122 bits left which can be randomly generated.<br>
You can generate UUID v4 by importing package from Google:<br>
https://github.com/google/uuid
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
uuid := uuid.New()
fmt.Println(uuid.String())
}
Also, you can try package I created. It's very light weight and easy to understand. https://github.com/bitactro/UUIDv4 <br>
package main
import (
"fmt"
"github.com/bitactro/UUIDv4"
)
func main() {
fmt.Println(uuidv4.GenerateUUID4())
}
答案13
得分: 1
// +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
}
英文:
For Windows, I did recently this:
// +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
}
答案14
得分: 1
这个库是我们用于生成和解析uuid的标准:
https://github.com/pborman/uuid
答案15
得分: 1
The https://github.com/google/uuid module based on RFC 4122 and UUID V4 is currently supported. If you want to use the latest UUID version like UUID v7,
This module https://github.com/uuid6/uuid6go-proto could be used.
UUID version 7: An entirely new time-based UUID bit layout sourced from the widely implemented and well known Unix Epoch timestamp source.
unix_ts_ms|ver|rand_a|var|rand_b
Since the UUID V4 contains random and it is not used for sorting. However, there is a timestamp part on UUID V7, it would be more friendly for sorting.
Sample
var gen uuid.UUIDv7Generator
uuid := gen.Next()
fmt.Println(uuid.ToString())
fmt.Println(uuid.Time())
fmt.Println(uuid.Timestamp())
Output
0632933765-357c-31b6-ed56-0daba726b1
2022-09-20 11:28:54 +0800 CST
1663644534
英文:
The https://github.com/google/uuid module based on RFC 4122 and UUID V4 is currently supported. If you want to use the latest UUID version like UUID v7,
This module https://github.com/uuid6/uuid6go-proto could be used.
UUID version 7: An entirely new time-based UUID bit layout sourced from the widely implemented and well known Unix Epoch timestamp source.
unix_ts_ms|ver|rand_a|var|rand_b
Since the UUID V4 contains random and it is not used for sorting. However, there is a timestamp part on UUID V7, it would be more friendly for sorting.
Sample
var gen uuid.UUIDv7Generator
uuid := gen.Next()
fmt.Println(uuid.ToString())
fmt.Println(uuid.Time())
fmt.Println(uuid.Timestamp())
Output
0632933765-357c-31b6-ed56-0daba726b1
2022-09-20 11:28:54 +0800 CST
1663644534
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论