完善依赖

This commit is contained in:
eson 2019-01-06 05:48:59 +08:00
parent f827851cf4
commit 086b040c52
6 changed files with 136 additions and 97 deletions

6
Gopkg.lock generated
View File

@ -85,12 +85,12 @@
version = "v1.4.1" version = "v1.4.1"
[[projects]] [[projects]]
digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925" branch = "master"
digest = "1:a3b8912deeef29007fab9a13a9f21b9e9b59c621a2ed61e2fe7b37320a71fbd5"
name = "github.com/satori/go.uuid" name = "github.com/satori/go.uuid"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3" revision = "b2ce2384e17bbe0c6d34077efa39dbab3e09123b"
version = "v1.2.0"
[[projects]] [[projects]]
digest = "1:2cab41f59638fdb77dda96ab4f9b5860ef30f48967557254eba127e43c756f2e" digest = "1:2cab41f59638fdb77dda96ab4f9b5860ef30f48967557254eba127e43c756f2e"

View File

@ -50,6 +50,10 @@
name = "github.com/tidwall/gjson" name = "github.com/tidwall/gjson"
version = "1.1.3" version = "1.1.3"
[[override]]
name = "github.com/satori/go.uuid"
branch = "master"
[prune] [prune]
go-tests = true go-tests = true
unused-packages = true unused-packages = true

1
article/vendor Symbolic link
View File

@ -0,0 +1 @@
../vendor

View File

@ -1,14 +1,12 @@
language: go language: go
sudo: false sudo: false
go: go:
- 1.2 - 1.6.x
- 1.3 - 1.7.x
- 1.4 - 1.8.x
- 1.5 - 1.9.x
- 1.6 - 1.10.x
- 1.7 - 1.11.x
- 1.8
- 1.9
- tip - tip
matrix: matrix:
allow_failures: allow_failures:

View File

@ -1,8 +1,8 @@
# UUID package for Go language # UUID package for Go language
[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) [![Build Status](https://travis-ci.org/satori/go.uuid.svg?branch=master)](https://travis-ci.org/satori/go.uuid)
[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) [![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid)
[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) [![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.svg)](http://godoc.org/github.com/satori/go.uuid)
This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs.
@ -23,7 +23,7 @@ Use the `go` command:
## Requirements ## Requirements
UUID package requires Go >= 1.2. UUID package tested against Go >= 1.6.
## Example ## Example
@ -37,13 +37,23 @@ import (
func main() { func main() {
// Creating UUID Version 4 // Creating UUID Version 4
u1 := uuid.NewV4() // panic on error
u1 := uuid.Must(uuid.NewV4())
fmt.Printf("UUIDv4: %s\n", u1) fmt.Printf("UUIDv4: %s\n", u1)
// or error handling
u2, err := uuid.NewV4()
if err != nil {
fmt.Printf("Something went wrong: %s", err)
return
}
fmt.Printf("UUIDv4: %s\n", u2)
// Parsing UUID from string input // Parsing UUID from string input
u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil { if err != nil {
fmt.Printf("Something gone wrong: %s", err) fmt.Printf("Something went wrong: %s", err)
return
} }
fmt.Printf("Successfully parsed: %s", u2) fmt.Printf("Successfully parsed: %s", u2)
} }

View File

@ -26,7 +26,9 @@ import (
"crypto/rand" "crypto/rand"
"crypto/sha1" "crypto/sha1"
"encoding/binary" "encoding/binary"
"fmt"
"hash" "hash"
"io"
"net" "net"
"os" "os"
"sync" "sync"
@ -37,21 +39,23 @@ import (
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). // UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000 const epochStart = 122192928000000000
var ( type epochFunc func() time.Time
global = newDefaultGenerator() type hwAddrFunc func() (net.HardwareAddr, error)
var (
global = newRFC4122Generator()
epochFunc = unixTimeFunc
posixUID = uint32(os.Getuid()) posixUID = uint32(os.Getuid())
posixGID = uint32(os.Getgid()) posixGID = uint32(os.Getgid())
) )
// NewV1 returns UUID based on current timestamp and MAC address. // NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID { func NewV1() (UUID, error) {
return global.NewV1() return global.NewV1()
} }
// NewV2 returns DCE Security UUID based on POSIX UID/GID. // NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID { func NewV2(domain byte) (UUID, error) {
return global.NewV2(domain) return global.NewV2(domain)
} }
@ -61,7 +65,7 @@ func NewV3(ns UUID, name string) UUID {
} }
// NewV4 returns random generated UUID. // NewV4 returns random generated UUID.
func NewV4() UUID { func NewV4() (UUID, error) {
return global.NewV4() return global.NewV4()
} }
@ -72,74 +76,85 @@ func NewV5(ns UUID, name string) UUID {
// Generator provides interface for generating UUIDs. // Generator provides interface for generating UUIDs.
type Generator interface { type Generator interface {
NewV1() UUID NewV1() (UUID, error)
NewV2(domain byte) UUID NewV2(domain byte) (UUID, error)
NewV3(ns UUID, name string) UUID NewV3(ns UUID, name string) UUID
NewV4() UUID NewV4() (UUID, error)
NewV5(ns UUID, name string) UUID NewV5(ns UUID, name string) UUID
} }
// Default generator implementation. // Default generator implementation.
type generator struct { type rfc4122Generator struct {
storageOnce sync.Once clockSequenceOnce sync.Once
hardwareAddrOnce sync.Once
storageMutex sync.Mutex storageMutex sync.Mutex
rand io.Reader
epochFunc epochFunc
hwAddrFunc hwAddrFunc
lastTime uint64 lastTime uint64
clockSequence uint16 clockSequence uint16
hardwareAddr [6]byte hardwareAddr [6]byte
} }
func newDefaultGenerator() Generator { func newRFC4122Generator() Generator {
return &generator{} return &rfc4122Generator{
epochFunc: time.Now,
hwAddrFunc: defaultHWAddrFunc,
rand: rand.Reader,
}
} }
// NewV1 returns UUID based on current timestamp and MAC address. // NewV1 returns UUID based on current timestamp and MAC address.
func (g *generator) NewV1() UUID { func (g *rfc4122Generator) NewV1() (UUID, error) {
u := UUID{} u := UUID{}
timeNow, clockSeq, hardwareAddr := g.getStorage() timeNow, clockSeq, err := g.getClockSequence()
if err != nil {
return Nil, err
}
binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq) binary.BigEndian.PutUint16(u[8:], clockSeq)
hardwareAddr, err := g.getHardwareAddr()
if err != nil {
return Nil, err
}
copy(u[10:], hardwareAddr) copy(u[10:], hardwareAddr)
u.SetVersion(V1) u.SetVersion(V1)
u.SetVariant(VariantRFC4122) u.SetVariant(VariantRFC4122)
return u return u, nil
} }
// NewV2 returns DCE Security UUID based on POSIX UID/GID. // NewV2 returns DCE Security UUID based on POSIX UID/GID.
func (g *generator) NewV2(domain byte) UUID { func (g *rfc4122Generator) NewV2(domain byte) (UUID, error) {
u := UUID{} u, err := g.NewV1()
if err != nil {
timeNow, clockSeq, hardwareAddr := g.getStorage() return Nil, err
}
switch domain { switch domain {
case DomainPerson: case DomainPerson:
binary.BigEndian.PutUint32(u[0:], posixUID) binary.BigEndian.PutUint32(u[:], posixUID)
case DomainGroup: case DomainGroup:
binary.BigEndian.PutUint32(u[0:], posixGID) binary.BigEndian.PutUint32(u[:], posixGID)
} }
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
u[9] = domain u[9] = domain
copy(u[10:], hardwareAddr)
u.SetVersion(V2) u.SetVersion(V2)
u.SetVariant(VariantRFC4122) u.SetVariant(VariantRFC4122)
return u return u, nil
} }
// NewV3 returns UUID based on MD5 hash of namespace UUID and name. // NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func (g *generator) NewV3(ns UUID, name string) UUID { func (g *rfc4122Generator) NewV3(ns UUID, name string) UUID {
u := newFromHash(md5.New(), ns, name) u := newFromHash(md5.New(), ns, name)
u.SetVersion(V3) u.SetVersion(V3)
u.SetVariant(VariantRFC4122) u.SetVariant(VariantRFC4122)
@ -148,17 +163,19 @@ func (g *generator) NewV3(ns UUID, name string) UUID {
} }
// NewV4 returns random generated UUID. // NewV4 returns random generated UUID.
func (g *generator) NewV4() UUID { func (g *rfc4122Generator) NewV4() (UUID, error) {
u := UUID{} u := UUID{}
g.safeRandom(u[:]) if _, err := io.ReadFull(g.rand, u[:]); err != nil {
return Nil, err
}
u.SetVersion(V4) u.SetVersion(V4)
u.SetVariant(VariantRFC4122) u.SetVariant(VariantRFC4122)
return u return u, nil
} }
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. // NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func (g *generator) NewV5(ns UUID, name string) UUID { func (g *rfc4122Generator) NewV5(ns UUID, name string) UUID {
u := newFromHash(sha1.New(), ns, name) u := newFromHash(sha1.New(), ns, name)
u.SetVersion(V5) u.SetVersion(V5)
u.SetVariant(VariantRFC4122) u.SetVariant(VariantRFC4122)
@ -166,66 +183,61 @@ func (g *generator) NewV5(ns UUID, name string) UUID {
return u return u
} }
func (g *generator) initStorage() { // Returns epoch and clock sequence.
g.initClockSequence() func (g *rfc4122Generator) getClockSequence() (uint64, uint16, error) {
g.initHardwareAddr() var err error
} g.clockSequenceOnce.Do(func() {
func (g *generator) initClockSequence() {
buf := make([]byte, 2) buf := make([]byte, 2)
g.safeRandom(buf) if _, err = io.ReadFull(g.rand, buf); err != nil {
g.clockSequence = binary.BigEndian.Uint16(buf)
}
func (g *generator) initHardwareAddr() {
interfaces, err := net.Interfaces()
if err == nil {
for _, iface := range interfaces {
if len(iface.HardwareAddr) >= 6 {
copy(g.hardwareAddr[:], iface.HardwareAddr)
return return
} }
g.clockSequence = binary.BigEndian.Uint16(buf)
})
if err != nil {
return 0, 0, err
} }
}
// Initialize hardwareAddr randomly in case
// of real network interfaces absence
g.safeRandom(g.hardwareAddr[:])
// Set multicast bit as recommended in RFC 4122
g.hardwareAddr[0] |= 0x01
}
func (g *generator) safeRandom(dest []byte) {
if _, err := rand.Read(dest); err != nil {
panic(err)
}
}
// Returns UUID v1/v2 storage state.
// Returns epoch timestamp, clock sequence, and hardware address.
func (g *generator) getStorage() (uint64, uint16, []byte) {
g.storageOnce.Do(g.initStorage)
g.storageMutex.Lock() g.storageMutex.Lock()
defer g.storageMutex.Unlock() defer g.storageMutex.Unlock()
timeNow := epochFunc() timeNow := g.getEpoch()
// Clock changed backwards since last UUID generation. // Clock didn't change since last UUID generation.
// Should increase clock sequence. // Should increase clock sequence.
if timeNow <= g.lastTime { if timeNow <= g.lastTime {
g.clockSequence++ g.clockSequence++
} }
g.lastTime = timeNow g.lastTime = timeNow
return timeNow, g.clockSequence, g.hardwareAddr[:] return timeNow, g.clockSequence, nil
}
// Returns hardware address.
func (g *rfc4122Generator) getHardwareAddr() ([]byte, error) {
var err error
g.hardwareAddrOnce.Do(func() {
if hwAddr, err := g.hwAddrFunc(); err == nil {
copy(g.hardwareAddr[:], hwAddr)
return
}
// Initialize hardwareAddr randomly in case
// of real network interfaces absence.
if _, err = io.ReadFull(g.rand, g.hardwareAddr[:]); err != nil {
return
}
// Set multicast bit as recommended by RFC 4122
g.hardwareAddr[0] |= 0x01
})
if err != nil {
return []byte{}, err
}
return g.hardwareAddr[:], nil
} }
// Returns difference in 100-nanosecond intervals between // Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time. // UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function. func (g *rfc4122Generator) getEpoch() uint64 {
func unixTimeFunc() uint64 { return epochStart + uint64(g.epochFunc().UnixNano()/100)
return epochStart + uint64(time.Now().UnixNano()/100)
} }
// Returns UUID based on hashing of namespace UUID and name. // Returns UUID based on hashing of namespace UUID and name.
@ -237,3 +249,17 @@ func newFromHash(h hash.Hash, ns UUID, name string) UUID {
return u return u
} }
// Returns hardware address.
func defaultHWAddrFunc() (net.HardwareAddr, error) {
ifaces, err := net.Interfaces()
if err != nil {
return []byte{}, err
}
for _, iface := range ifaces {
if len(iface.HardwareAddr) >= 6 {
return iface.HardwareAddr, nil
}
}
return []byte{}, fmt.Errorf("uuid: no HW address found")
}