क्या वहाँ एक विधि है जो भाषा के साथ UUID उत्पन्न करती है


109

मेरे पास कोड है जो इस तरह दिखता है:

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 है, और कोड है कि संशोधित के मूल्य का उद्देश्य क्या है u[8]और u[6]

क्या UUIDs बनाने का एक बेहतर तरीका है?


1
यह उत्तर अब अधिक उपयुक्त लगता है।
viKiG

जवाबों:


32
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, जो कि एक यूयूआईडी के लिए सभी वैध मूल्य नहीं हैं। जहाँ तक मैं बता सकता हूँ, यह हालांकि टुकड़ा में सभी मूल्यों के लिए किया जाना चाहिए।

यदि आप लिनक्स पर हैं, तो आप वैकल्पिक रूप से कॉल कर सकते हैं /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

23
विशेष रूप से, यह दृष्टिकोण धीमा है; 2012 की मैकबुक एयर पर यह रणनीति केवल 170 uuids / second का उत्पादन कर सकती है।
जय टेलर

12
और nu7hatch / gouuid लाइब्रेरी का उपयोग करके, मैं 172,488 uuids / सेकंड उत्पन्न करने में सक्षम था।
जे टेलर

2
u[6]और u[8]बाइट्स की अच्छी व्याख्या ।
चौबे

3
अपने सिस्टम पर (Ubuntu 15.10) मुझे न्यूलाइन वर्ण को हटाने के लिए स्ट्रिंग्स के माध्यम से कमांड आउटपुट को चलाने की आवश्यकता है। ट्रिम (स्ट्रिंग (आउट)), अन्यथा इसे एक अनुगामी के रूप में इनपुट किया गया था? फाइल सिस्टम में चरित्र।
1

39
एक बाहरी कार्यक्रम को कॉल करना जो मौजूद हो सकता है या नहीं हो सकता है, यह काफी सरल कार्य करने के लिए एक भयानक तरीका है।
टिमम्म 10

96

आप यू -यूआईडी को गो-यूआईडी लाइब्रेरी का उपयोग करके उत्पन्न कर सकते हैं । इसके साथ स्थापित किया जा सकता है:

go get github.com/nu7hatch/gouuid

आप के साथ यादृच्छिक (4 संस्करण) UUIDs उत्पन्न कर सकते हैं:

import "github.com/nu7hatch/gouuid"

...

u, err := uuid.NewV4()

लौटा UUIDप्रकार 16 बाइट सरणी है, जिससे आप बाइनरी मान आसानी से प्राप्त कर सकते हैं। यह अपनी String()विधि के माध्यम से मानक हेक्स स्ट्रिंग प्रतिनिधित्व भी प्रदान करता है ।

आपके पास ऐसा कोड भी दिखता है जैसे कि यह एक मान्य संस्करण 4 UUID भी उत्पन्न करेगा: अंत में आप जो बिटवाइज़ हेरफेर करते हैं, वह UUID के संस्करण और वैरिएंट फ़ील्ड को सही रूप से संस्करण 4 के रूप में पहचानने के लिए सेट करता है । यह अन्य एल्गोरिदम (जैसे आपके मैक पते और समय के आधार पर संस्करण 1 यूयूआईडी) के माध्यम से उत्पन्न लोगों से यादृच्छिक यूयूआईडी को अलग करने के लिए किया जाता है।


2
@ लोग जो नहीं जानते कि वे जो कर रहे हैं, वह सबसे अधिक सच है। अनावश्यक निर्भरता का परिचय हमेशा एक बुरी चीज है।
एरिक एग्नर

31
@ErikAigner जब तक यह 50 पंक्तियाँ हैं, मुझे इसके बारे में सोचने, लिखने और परीक्षण करने की आवश्यकता नहीं है, मैं उन्हें धन्यवाद देता हूँ .. मेरे पास ऐसा करने के लिए अन्य सामान है, फिर पहिया को सुदृढ़ करें।
रिका

3
यह पुस्तकालय ऐसा लगता है कि यह वास्तव में RFC4122 अनुरूप नहीं है: github.com/nu7hatch/gouuid/issues/28 (वर्तमान में 2/1/2016 के अनुसार खुला मुद्दा)
चार्ल्स एल।

1
@EricAigner पहिए को फिर से लगाना भी थोड़े अनावश्यक है। यदि एक पुस्तकालय मौजूद है और यह अच्छी तरह से करता है तो परेशान क्यों न करें कि यदि आप इसे करना सीखते हैं तो आप अपने काम को कैसे करें।
सर

4
@ErikAigner मुझे बस वह उपहास लगता है। कोई भी पहले से ही किए गए सामान को फिर से नहीं बनाता है जब तक कि आप बेहतर नहीं कर सकते हैं या आपको अपने कार्यक्रम के लिए कुछ विशिष्ट करने की आवश्यकता नहीं है, यदि आप कोड का निरीक्षण करते हैं और देखते हैं कि यह अच्छी तरह से करता है तो इसे स्वयं परेशान क्यों करें - न केवल आप विकास के समय और लागत को बर्बाद करते हैं, आप भी हैं संभावित रूप से बग या बस गलत कार्यान्वयन में लाने के लिए यदि आप पूरी तरह से नहीं जानते हैं कि आप क्या कर रहे हैं, तो इन पुस्तकालयों को आमतौर पर ऐसे लोगों को बनाया जाता है जो जानते हैं कि वे क्या कर रहे हैं। यह तीसरे पक्ष के पुस्तकालयों का उपयोग करने के लिए धोखेबाज़ नहीं है, इसकी केवल धोखेबाज़ यह मानती है कि यह काम करता है और पहले कोड का निरीक्षण नहीं करता है ..
सर

70

go-uuidपुस्तकालय RFC4122 संगत नहीं है। वेरिएंट बिट्स सही तरीके से सेट नहीं हैं। समुदाय के सदस्यों द्वारा इसे ठीक करने के कई प्रयास किए गए हैं, लेकिन फिक्स के लिए पुल अनुरोध स्वीकार नहीं किए जा रहे हैं।

आप लाइब्रेरी के आधार पर I uwrote जाओ uuid लाइब्रेरी का उपयोग करके UUIDs उत्पन्न कर सकते हैं go-uuid। कई सुधार और सुधार हैं। इसके साथ स्थापित किया जा सकता है:

go get github.com/twinj/uuid

आप के साथ यादृच्छिक (4 संस्करण) UUIDs उत्पन्न कर सकते हैं:

import "github.com/twinj/uuid"

u := uuid.NewV4()

लौटाया गया UUID प्रकार एक इंटरफ़ेस है और अंतर्निहित प्रकार एक सरणी है।

पुस्तकालय भी v1 UUIDs उत्पन्न करता है और सही ढंग से v3 और 5 UUIDs उत्पन्न करता है। मौजूदा डेटा के आधार पर UUIDs बनाने के लिए मुद्रण और स्वरूपण और नए सामान्य तरीकों के साथ मदद करने के लिए कई नए तरीके हैं।


4
मुझे यह पैकेज पसंद है। मैंने आधिकारिक तौर पर इसे अपने सभी अनुप्रयोगों के लिए अपनाया है। मैंने पाया कि nu7hatch पैकेज RFC4122-compliant नहीं था।
रिचर्ड एनजी

+1 सहमत, अद्यतन और मुद्रण / स्वरूपण एक्सटेंशन पहले से ही शामिल हैं।
eduncan911

4
अस्वीकरण गायब है? : p
चक्री

3
पुस्तकालय "नीचे" क्या है? आपको SO पर ऊपर और नीचे का उपयोग करने से बचना चाहिए क्योंकि यह बहुत जल्दी बदल सकता है।
स्टीफन डॉलबर्ग

वहाँ भी एक और समान, satori / go.uuid है । अभी तक कोशिश नहीं की, लेकिन मैं इसे nu7hatch मृत परियोजना के प्रतिस्थापन के रूप में उपयोग करने जा रहा हूं ...
shadyyx

52

"क्रिप्टो / रैंड" यादृच्छिक बाइट्स उत्पत्ति के लिए क्रॉस प्लेटफ़ॉर्म pkg है

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
}

3
pseudo_uuidक्योंकि यह मैक पते की तरह गैर-यादृच्छिक पहचानकर्ताओं को गायब कर रहा है और जो कुछ भी RFC4122 निर्दिष्ट है? तो यह वास्तव में अधिक यादृच्छिक है।
Xeoncross

2
अच्छा उत्तर; मैंने इसे stackoverflow.com/a/48134820/1122270 पर विस्तारित किया है , और मुझे लगता है कि बहुत से लोगों को वास्तव में UUIDs का विशेष रूप से उपयोग करने की आवश्यकता नहीं है (और न ही sha1 / sha256 जिसे मैंने सोचा था कि मुझे अपने यादृच्छिक उपयोग के लिए उपयोग करने की आवश्यकता है) आईडी की समस्या), लेकिन बस कुछ यादृच्छिक और अद्वितीय चाहते हैं, और आपका नमूना एक समाधान के लिए एक अच्छी शुरुआत प्रदान करता है
cnst

धन्यवाद! पर्याप्त सरल
कार्ल पोकस

1. यह किसी भी मानक का पालन नहीं करता है। 2. सिर्फ %xबाइट मान के साथ मुद्दों का उपयोग करना 128 से कम है, आपको पैडिंग लागू करने की आवश्यकता है, %04xबाइट जोड़ी के लिए
23'19

38

Google द्वारा एक आधिकारिक कार्यान्वयन है: https://github.com/google/uuid

एक संस्करण बनाना 4 यूयूआईडी इस तरह काम करता है:

package main

import (
    "fmt"
    "github.com/google/uuid"
)

func main() {
    id := uuid.New()
    fmt.Println(id.String())
}

इसे यहाँ आज़माएँ: https://play.golang.org/p/6YPi1djUMj9


1
Godoc उपयोग करने की सलाह New()और यह के बराबर हैuuid.Must(uuid.NewRandom())
जिम

@ जय: तुम सही हो! मैंने उसी हिसाब से अपना जवाब अपडेट किया।
शुतफान

ध्यान दें कि नया () "घातक" हो सकता है (जो कुछ मामलों में ठीक है)। ऐसे मामलों में जब आप अपने प्रोग्राम को घातक नहीं बनाना चाहते हैं, केवल uuid.NewRandom () का उपयोग करें - जो UUID और एक त्रुटि देता है।
तोमर

@ टॉमर: सच! हालांकि मुझे आश्चर्य है कि यह वास्तव में किन परिस्थितियों में होगा। यह कोड का प्रासंगिक हिस्सा है: github.com/google/uuid/blob/… डिफ़ॉल्ट रूप से पाठक एक है rand.Reader। मुझे यकीन नहीं है कि अगर कोई एक त्रुटि लौटाएगा या यदि यह केवल एक कस्टम रीडर के साथ हो सकता है ...
shutefan

1
हाय @ शुतफान - मैं मानता हूं कि यह दुर्लभ हो सकता है। rand.Reader कॉल कर्नेल फ़ंक्शन ( golang.org/src/crypto/rand/rand.go ) कहता है । ये कुछ परिदृश्यों में विफल हो सकते हैं।
तोमर


12

Russ कॉक्स के पोस्ट से :

कोई आधिकारिक पुस्तकालय नहीं है। त्रुटि जाँच को अनदेखा करना, ऐसा लगता है कि यह ठीक काम करेगा:

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:])

नोट: मूल में, पूर्व गो 1 संस्करण पहली पंक्ति थी:

f, _ := os.Open("/dev/urandom", os.O_RDONLY, 0)

यहाँ यह संकलित करता है और क्रियान्वित करता है, केवल /dev/urandomखेल के मैदान में सभी शून्य देता है। स्थानीय स्तर पर ठीक काम करना चाहिए।

उसी धागे में कुछ अन्य तरीके / संदर्भ / पैकेज पाए जाते हैं।


12
हालांकि यह एक वैध यूयूआईडी उत्पन्न नहीं करेगा: संस्करण 4 यूयूआईडी (यादृच्छिक डेटा पर आधारित प्रकार) को गैर-यादृच्छिक यूयूआईडी प्रारूपों के साथ संघर्ष से बचने के लिए कुछ निश्चित तरीके से सेट करने की आवश्यकता होती है।
जेम्स हेनस्ट्रिज

4
import "crypto/rand"मेरी राय में उपयोग करने के लिए बेहतर है , लेकिन +1 के लिए uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])। ओपी के कोड के साथ संयुक्त, और यह बहुत अच्छा काम करता है।
चौबे

2
क्रिप्टो / रैंड पैकेज का उपयोग करना: play.golang.org/p/7JJDx4GL77 । zzzz का कोड वह करता है जो क्रिप्ट / रैंड करता है, सिवाय इसके कि यह उन प्लेटफार्मों को भी कवर करता है जो समर्थन नहीं करते हैं / dev / urandom (विंडोज)।
ड्रू

यह ध्यान दिया जाना चाहिए कि यह प्लेटफ़ॉर्म विशिष्ट है
Dan Esparza

2
@Matt: समस्या यह है कि अन्य UUID प्रारूप किसी अन्य प्राधिकरण (जैसे कि आपका ईथरनेट मैक पता अद्वितीय है) को सौंपकर अपनी विशिष्टता प्राप्त करते हैं, और फिर इसे किसी और चीज़ (जैसे समय और एक काउंटर) के साथ जोड़कर। यदि आप एक यादृच्छिक UUID का उत्पादन करते हैं जो V4 के रूप में सही रूप से स्वरूपित नहीं है, तो आप सिस्टम को कमजोर कर रहे हैं।
जेम्स हेनस्ट्रिज

8

Uuid कल्पना के भाग के रूप में, यदि आप यादृच्छिक से एक uuid उत्पन्न करते हैं, तो इसमें 13 वें वर्ण के रूप में "4" और 17 वें ( स्रोत ) में "8", "9", "a" या "b" होना चाहिए ।

// 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 

4

Gorand पैकेज एक UUID विधि है कि रिटर्न एक संस्करण 4 (अनियमित रूप से उत्पन्न) UUID अपने विहित स्ट्रिंग प्रतिनिधित्व में ( "XXXXXXXXXXXX-XXXXXXXX-XXXXXXXXXXXX") और यह आरएफसी 4122 अनुरूप है।

यह गो द्वारा समर्थित सभी प्लेटफार्मों में UUIDs की सबसे क्रिप्टोग्राफिक रूप से सुरक्षित पीढ़ी को सुनिश्चित करने के लिए क्रिप्टो / रैंड पैकेज का भी उपयोग करता है।

import "github.com/leonelquinteros/gorand"

func main() {
    uuid, err := gorand.UUID()
    if err != nil {
        panic(err.Error())
    }

    println(uuid)
} 

4

लिनक्स पर, आप इससे पढ़ सकते हैं /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

4
डाउनवोटेड क्योंकि सीधे प्रोग्रामिंग भाषा में होस्ट-प्लेटफॉर्म के आधार पर जो मल्टी-प्लेटफॉर्म एप्लिकेशन के लिए उपयोग किया जाता है, बाहरी निर्भरता से भी बदतर है।
बाईबेई

1
प्रोग्रामिंग भाषा मल्टीप्लेट रिकॉर्डर हो सकती है, लेकिन यह लिनक्स के लिए विशिष्ट समाधान है जो कभी भी अन्य प्लेटफॉर्म पर नहीं होगा, इसलिए, यह एक मान्य प्रतिक्रिया आईएमओ है।
टन

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
}

2
डाउनवोटेड क्योंकि सीधे प्रोग्रामिंग भाषा में होस्ट-प्लेटफॉर्म के आधार पर जो मल्टी-प्लेटफॉर्म एप्लिकेशन के लिए उपयोग किया जाता है, बाहरी निर्भरता से भी बदतर है।
बाईबाई

1
@ बेइबे, मुझे आश्चर्य है कि आप अपने आप को यह तय करने के लिए एक अधिकारी क्यों मानते हैं कि "क्या बदतर है" (और क्या नहीं है) इस प्रश्न के सभी उत्तरों के माध्यम से स्किम करें और सभी को "सिस्टम-निर्भर" बता दें? ये उत्तर) सभी संभावित विकल्पों के क्षितिज को चौड़ा करने के लिए दिए गए थे, और बी) सामूहिक रूप से एक पूरी तस्वीर पेश करते हैं तो कृपया बचकाने "एसओ खेल" को रोकें और कार्रवाई करने से पहले कुछ सोचें।
कोस्टिक्स

संक्षिप्त जवाब। लिखने योग्य कोड। आपका उत्तर किसी भिन्न प्लेटफ़ॉर्म पर पोर्ट नहीं किया जा सकता है। इसलिए यदि ओपी अपने आवेदन को दूसरे प्लेटफॉर्म पर ले जाना चाहेगा तो आवेदन टूट जाएगा। मेरे पास प्लेटफ़ॉर्म आश्रित कोड लिखने वाले लोगों का मेरा उचित हिस्सा है, जहां यह पूरी तरह से अनावश्यक है और यह अधिक परेशानी पैदा करता है फिर इसका मूल्य है। आप सिर्फ अपने लिए कोड नहीं लिखते हैं। आप उन लोगों के लिए कोड लिखते हैं जो आपके जाने के बाद इसे बनाए रखेंगे। इसलिए यह उत्तर उचित नहीं है। कोई कारण नहीं है कि मैं होमिनेंस का सहारा ले और मुझे बचकाना कहे।
बयबाई

1
@ बेइबे, मैंने ओवररिएक्ट किया, इसलिए कृपया मुझे हमले के लिए क्षमा करें। मैं आपके कारणों के प्रति आश्वस्त नहीं हूँ, फिर भी, लेकिन माना जाता है कि "चलो असहमत हैं" मामला।
कोस्टिक्स

1

यह पुस्तकालय uuid पीढ़ी और पार्सिंग के लिए हमारा मानक है:

https://github.com/pborman/uuid


ध्यान दें कि Google की अपनी लाइब्रेरी ( github.com/google/uuid ) आंशिक रूप से github.com/pborman/uuid पर आधारित है , जिसने बदले में, Google द्वारा किए गए कुछ परिवर्तनों को वापस शामिल कर लिया है। हालांकि, कथित तौर पर, यदि आप इन परियोजनाओं में से किसी में योगदान करना चाहते हैं, तो आपको एक योगदानकर्ता लाइसेंस समझौते (सीएलए) पर हस्ताक्षर करने (या हस्ताक्षर करने) की आवश्यकता है । अगस्त 2015 में यह स्पष्ट रूप से ऐसा नहीं था, जब आपका उत्तर जोड़ा गया था; @pborman ने कहा कि केवल 16 फरवरी 2016 को
ग्वेनेथ लेलेवेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.