[go] 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를 생성하는 더 좋은 방법이 있습니까?



답변

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

이 행은 바이트 6 및 8의 값을 특정 범위로 고정합니다. UUID에 대해 모두 유효한 값이 아닌 rand.Read범위의 임의의 바이트를 반환합니다 0-255. 내가 말할 수있는 한, 이것은 슬라이스의 모든 값에 대해 수행되어야합니다.

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


답변

go-uuid 라이브러리를 사용하여 UUID를 생성 할 수 있습니다 . 다음과 함께 설치할 수 있습니다.

go get github.com/nu7hatch/gouuid

다음을 사용하여 임의 (버전 4) UUID를 생성 할 수 있습니다.

import "github.com/nu7hatch/gouuid"

...

u, err := uuid.NewV4()

반환 된 UUID유형은 16 바이트 배열이므로 이진 값을 쉽게 검색 할 수 있습니다. 또한 String()메서드 를 통해 표준 16 진 문자열 표현을 제공합니다 .

또한 코드는 유효한 버전 4 UUID를 생성하는 것처럼 보입니다. 마지막에 수행하는 비트 조작은 UUID의 버전 및 변형 필드를 설정하여 버전 4로 올바르게 식별합니다 . 이는 임의의 UUID를 다른 알고리즘 (예 : MAC 주소 및 시간을 기반으로 한 버전 1 UUID)을 통해 생성 된 것과 구별하기 위해 수행됩니다.


답변

go-uuid라이브러리는 RFC4122에 호환되지 않습니다. 변형 비트가 올바르게 설정되지 않았습니다. 커뮤니티 구성원이이 문제를 수정하려고 여러 번 시도했지만 수정에 대한 풀 요청이 수락되지 않았습니다.

라이브러리를 기반으로 다시 작성한 Go uuid 라이브러리를 사용하여 UUID를 생성 할 수 있습니다 go-uuid. 몇 가지 수정 및 개선 사항이 있습니다. 다음과 함께 설치할 수 있습니다.

go get github.com/twinj/uuid

다음을 사용하여 임의 (버전 4) UUID를 생성 할 수 있습니다.

import "github.com/twinj/uuid"

u := uuid.NewV4()

반환 된 UUID 유형은 인터페이스이고 기본 유형은 배열입니다.

라이브러리는 또한 v1 UUID를 생성하고 v3 및 5 UUID를 올바르게 생성합니다. 인쇄 및 서식 지정에 도움이되는 몇 가지 새로운 방법과 기존 데이터를 기반으로 UUID를 만드는 새로운 일반 방법이 있습니다.


답변

“crypto / rand”는 임의의 바이트 생성을위한 크로스 플랫폼 패키지입니다.

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
}


답변

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


답변

gofrs / UUID는 대한 대체 SATORI / go.uuid 는 IS, 이동에 가장 별표 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())


답변

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하며 플레이 그라운드의 모든 0 만 반환합니다. 로컬에서 잘 작동합니다.

같은 스레드에는 몇 가지 다른 메서드 / 참조 / 패키지가 있습니다.