Documentation ¶
Overview ¶
Package youyouayedee provides tools for working with Universally Unique Identifiers (UUIDs).
(A note for non-native English speakers and others confused by the package name: it is a phonetic spelling of the acronym "UUID". Since Go package names get imported into the caller's namespace, I didn't want to use the name "uuid" because that's a very common variable name for UUID values.)
There are 5 well-known UUID versions defined in RFC 4122:
Version 1 UUIDs are based on the current time (measured as hectonanoseconds since 1582-10-12T00:00:00Z on the Gregorian calendar, *including* leap seconds), a 14-bit rollover counter that is private to the generating host but shared across all software on the host that generates V1 UUIDs, and (last but not least) the generating host's "node identifier", which is traditionally the MAC address of the host's network card but which may be something else for privacy reasons, so long as it is stable and globally unique. The fields are also weirdly out of order, so they don't sort very well despite being monotonic-ish.
(NB: V1 UUIDs are extremely popular despite the fact that absolutely nobody correctly follows the spec when generating them.)
Version 2 UUIDs are based on the Open Software Foundation's Distributed Computing Environment specification. They are extremely rare.
Version 3 UUIDs are based on the MD5 hash of a namespace UUID and a string. Mostly obsolete because of MD5. Compare to V5 UUIDs.
Version 4 UUIDs are based on 122 bits chosen at random, plus 6 well-known bits to make it a valid UUID.
Version 5 UUIDs are just like V3 UUIDs, except that the hash function is SHA1 instead of MD5. Since malicious collision resistance is not actually a significant use case for most users of UUIDs, there's nothing actually wrong with V5 UUIDs despite SHA1 being extremely cryptographically broken in 2022. However, neither V3 nor V5 UUIDs have any significant advantages over V4 UUIDs. This library supports them but they are not recommended for general use. They can be good for generating well-known UUIDs defined in a specification, however.
In addition, this library supports the 3 additional UUID versions defined in the IETF document draft-peabody-dispatch-new-uuid-format-04, which this library's author is very excited about.
Version 6 UUIDs are based on the current time, counter, and node identifier just like V1 UUIDs, but their fields are rearranged to make them more sortable in databases. If you already have V1 UUIDs, you can convert them to V6 for database storage and then back again if you need the exact same V1 UUID.
Version 7 UUIDs, which are meant to fully replace V1 and V6 UUIDs, are also based on the current time. Unlike V1 and V6, they are based on the well-known and comparatively well-loved Unix time_t epoch (milliseconds since 1970-01-01T00:00:00Z, *excluding* leap seconds) and their meaning is thus much easier to grok with the tools given to you by the OS. The additional non-time bits are now left as the implementor's choice, with random bits or monotonic counters as proposed methods. Also, none of the bits are dedicated to sub-millisecond time precision, which few hosts are truly capable of providing *anyway* because they are not equipped with locally installed atomic clocks and NTP alone cannot achieve such accuracy.
Version 8 UUIDs are fully opaque, with their meaning defined exclusively by the implementor. As such, they cannot be expected to be "universally" unique across all software and all machines, but they may be useful in specific contexts. This library has limited support for them, but you will need to roll your own UUID generation algorithm (for obvious reasons).
Index ¶
- Constants
- Variables
- type ClockStorage
- type ClockStorageFile
- type ClockStorageUnavailable
- type DCEDomain
- type Decoded
- type EnumData
- type ErrClockNotFound
- type ErrHashFactoryIsNil
- type ErrInputNotValid
- type ErrLockNotSupported
- type ErrMethodNotSupported
- type ErrNamespaceNotValid
- type ErrOperationFailed
- type ErrParseFailed
- type ErrVersionMismatch
- type ErrVersionNotSupported
- type Generator
- type GeneratorBase
- type GeneratorFactory
- type GeneratorFactoryFunc
- type LeapSecondCalculator
- type LeapSecondCalculatorDummy
- type LeapSecondCalculatorFixed
- type Method
- type Node
- type Operation
- type Options
- type ParseProblem
- type TextUUID
- type UUID
- func (uuid UUID) AppendTo(out []byte) []byte
- func (uuid UUID) Convert(version Version, lsc LeapSecondCalculator) (UUID, error)
- func (uuid UUID) Decode(lsc LeapSecondCalculator) Decoded
- func (uuid UUID) Domain() DCEDomain
- func (uuid UUID) GoString() string
- func (uuid UUID) ID() uint32
- func (uuid UUID) IsMax() bool
- func (uuid UUID) IsValid() bool
- func (uuid UUID) IsZero() bool
- func (uuid UUID) MarshalBinary() ([]byte, error)
- func (uuid UUID) MarshalJSON() ([]byte, error)
- func (uuid UUID) MarshalText() ([]byte, error)
- func (uuid *UUID) Scan(value interface{}) error
- func (uuid UUID) String() string
- func (uuid UUID) URN() string
- func (uuid *UUID) UnmarshalBinary(data []byte) error
- func (uuid *UUID) UnmarshalJSON(data []byte) error
- func (uuid *UUID) UnmarshalText(text []byte) error
- func (uuid UUID) Value() (driver.Value, error)
- func (uuid UUID) Version() Version
- type Version
Constants ¶
const Size = 16
Size is the size of a UUID in bytes.
Variables ¶
var GeneratorsByVersion = make(map[Version]GeneratorFactory)
GeneratorsByVersion provides a hook for the NewGenerator function to construct user-defined Generator instances.
var Max = UUID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
Max is the maximum UUID, "ffffffff-ffff-ffff-ffff-ffffffffffff".
var Nil = UUID{}
Nil is the nil UUID, "00000000-0000-0000-0000-000000000000".
var NilNode = Node{}
NilNode represents the invalid nil node identifier, "00:00:00:00:00:00".
Functions ¶
This section is empty.
Types ¶
type ClockStorage ¶
type ClockStorage interface { // Load retrieves the last known timestamp and the last known counter // value for the given Node. // // If the implementation returns ErrClockNotFound for any reason, the // UUID generator is required to use the current time as the last known // timestamp and to generate a new random counter value from scratch. // // Implementations are not required to retain a (timestamp, counter) // tuple for each node; if there is no tuple stored for the given Node, // then ErrClockNotFound is the best choice of return value. // Load(Node) (time.Time, uint32, error) // Store associates the given last known timestamp and last known // counter value with the given Node, synchronizing the data to // persistent storage. // // Implementations are free to discard the (timestamp, counter) tuples // associated with any previous node identifiers upon receiving a Store // method call with a new node identifier. However, it may be // beneficial to retain one such tuple for each past node identifier, // at least when such node identifiers are flagged as both IsGlobal and // IsUnicast. // Store(Node, time.Time, uint32) error }
ClockStorage provides an interface for loading and storing clock counters on behalf of UUID generators.
UUID generators based on timestamps (versions 1, 6, and 7) need some form of persistent storage in order to prevent collisions. This interface provides that persistent storage.
type ClockStorageFile ¶ added in v0.3.0
type ClockStorageFile struct {
// contains filtered or unexported fields
}
ClockStorageFile is an implementation of ClockStorage that reads from and writes to a file while holding a lock.
func OpenClockStorageFile ¶ added in v0.2.0
func OpenClockStorageFile(fileName string) (*ClockStorageFile, error)
OpenClockStorageFile constructs an instance of ClockStorageFile.
func (*ClockStorageFile) Close ¶ added in v0.3.0
func (cs *ClockStorageFile) Close() error
type ClockStorageUnavailable ¶ added in v0.3.0
type ClockStorageUnavailable struct{}
ClockStorageUnavailable is a dummy implementation of ClockStorage that does not store anything.
type DCEDomain ¶ added in v0.2.0
type DCEDomain byte
DCEDomain indicates the type of identifier stored in a DCE-based UUID.
type Decoded ¶ added in v0.5.0
type Decoded struct { // Valid is true iff the UUID was successfully decoded to any degree. Valid bool // Version holds the detected UUID version. Version Version // HasTicks is true iff the Time and Ticks fields are valid. HasTicks bool // HasCounter is true iff the Counter field is valid. HasCounter bool // HasNode is true iff the Node field is valid. HasNode bool // HasData is true iff the Data field is valid. HasData bool // HasDomainAndID is true iff the Domain and ID fields are valid. HasDomainAndID bool // Time holds the decoded time extracted from a time-based UUID. Time time.Time // Ticks holds the raw tick count from a time-based UUID. // // For V1 and V6 UUIDs, this is hectonanoseconds since the start of the // Gregorian calendar in 1582, with leap seconds (probably) included. // // For V7 UUIDs, this is milliseconds since the start of the Unix epoch // in 1970, with leap seconds omitted. // Ticks int64 // Counter holds the raw counter value from a time-based UUID. // // Only valid for V1 and V6 UUIDs. // Counter int // Node holds the node identifier from a time-based UUID. // // Only valid for V1 and V6 UUIDs. // Node Node // Domain holds the DCE domain. // // Only valid for V2 UUIDs. // Domain DCEDomain // ID holds the DCE identifier. // // Only valid for V2 UUIDs. // ID uint32 // Data contains any additional random or opaque bytes, with the // variant and version bits cleared if applicable. // // For V1 and V6 UUIDs, this field is not used. // // For V7 UUIDs, this field contains all the bits from the UUID except // the timestamp. // // For V3, V4, V5, and V8 UUIDs, this field contains almost all bits // from the UUID. // Data []byte }
Decoded holds the results of decoding a UUID into its components.
type ErrClockNotFound ¶ added in v0.3.0
type ErrClockNotFound struct{}
ErrClockNotFound indicates that the ClockStorage Load method was unable to provide a (last known timestamp, last known counter value) tuple for the given Node.
func (ErrClockNotFound) Error ¶ added in v0.3.0
func (ErrClockNotFound) Error() string
type ErrHashFactoryIsNil ¶ added in v0.3.0
type ErrHashFactoryIsNil struct {
Version Version
}
ErrHashFactoryIsNil indicates that a Generator requires a hash.Hash factory callback.
func (ErrHashFactoryIsNil) Error ¶ added in v0.3.0
func (err ErrHashFactoryIsNil) Error() string
type ErrInputNotValid ¶ added in v0.4.0
type ErrInputNotValid struct {
Input UUID
}
ErrInputNotValid indicates that the input UUID is not a valid UUID.
func (ErrInputNotValid) Error ¶ added in v0.4.0
func (err ErrInputNotValid) Error() string
type ErrLockNotSupported ¶ added in v0.3.0
type ErrLockNotSupported struct{}
ErrLockNotSupported indicates that file locking is not supported on the current OS platform.
func (ErrLockNotSupported) Error ¶ added in v0.3.0
func (ErrLockNotSupported) Error() string
type ErrMethodNotSupported ¶ added in v0.3.0
type ErrMethodNotSupported struct {
Method Method
}
ErrMethodNotSupported indicates that the called Generator method is not supported by the implementation.
func (ErrMethodNotSupported) Error ¶ added in v0.3.0
func (err ErrMethodNotSupported) Error() string
type ErrNamespaceNotValid ¶ added in v0.3.0
ErrNamespaceNotValid indicates that a Generator requires a valid namespace UUID.
func (ErrNamespaceNotValid) Error ¶ added in v0.3.0
func (err ErrNamespaceNotValid) Error() string
type ErrOperationFailed ¶ added in v0.3.0
ErrOperationFailed indicates that a required step failed while initializing a Generator or generating a UUID.
func (ErrOperationFailed) Error ¶ added in v0.3.0
func (err ErrOperationFailed) Error() string
func (ErrOperationFailed) Unwrap ¶ added in v0.3.0
func (err ErrOperationFailed) Unwrap() error
type ErrParseFailed ¶ added in v0.3.0
type ErrParseFailed struct { Input []byte Problem ParseProblem Args []interface{} Index uint ExpectByte byte ActualByte byte }
ErrParseFailed indicates that the input string could not be parsed as a UUID.
func (ErrParseFailed) Error ¶ added in v0.3.0
func (err ErrParseFailed) Error() string
type ErrVersionMismatch ¶ added in v0.3.0
ErrVersionMismatch indicates that a Generator constructor is not implemented for UUIDs of the given Version.
func (ErrVersionMismatch) Error ¶ added in v0.3.0
func (err ErrVersionMismatch) Error() string
type ErrVersionNotSupported ¶ added in v0.3.0
type ErrVersionNotSupported struct {
Version Version
}
ErrVersionNotSupported indicates that NewGenerator does not know how to generate UUIDs of the given Version.
func (ErrVersionNotSupported) Error ¶ added in v0.3.0
func (err ErrVersionNotSupported) Error() string
type Generator ¶
type Generator interface { // NewUUID generates a new unpredictable UUID. // // Generators are not required to support this operation, and should // return ErrMethodNotSupported{MethodNewUUID} if it is not. // NewUUID() (UUID, error) // NewHashUUID generates a new deterministic UUID by hashing the given // input data. // // Generators are not required to support this operation, and should // return ErrMethodNotSupported{MethodNewHashUUID} if it is not. // NewHashUUID(data []byte) (UUID, error) }
Generator is an interface for generating new UUID values.
func NewGenerator ¶
NewGenerator initializes a new Generator instance for the given UUID version.
If this library does not know how to generate UUIDs of the given version, then ErrVersionNotSupported is returned.
The GeneratorsByVersion global variable may be used to override this function's default behavior for chosen UUID versions.
func NewHashGenerator ¶
NewHashGenerator constructs a new Generator that produces hash-based UUIDs.
Versions 3, 5, and 8 are supported. Options must specify a valid, non-nil UUID in the Namespace field. For version 8 only, Options must also specify a valid, non-nil HashFactory callback.
func NewRandomGenerator ¶
NewRandomGenerator constructs a new Generator that produces new randomly generated UUIDs.
Versions 4 and 8 are supported.
type GeneratorBase ¶ added in v0.3.0
type GeneratorBase struct{}
GeneratorBase is a base Generator implementation that you can embed into the struct of your custom Generator implementation. All Generator methods will then have default implementations that simply return ErrMethodNotSupported.
This is a very easy way to future-proof your code for resiliency during future major version updates affecting the Generator interface.
func (GeneratorBase) NewHashUUID ¶ added in v0.3.0
func (GeneratorBase) NewHashUUID(data []byte) (UUID, error)
func (GeneratorBase) NewUUID ¶ added in v0.3.0
func (GeneratorBase) NewUUID() (UUID, error)
type GeneratorFactory ¶
GeneratorFactory is an interface for constructing Generator instances.
It is used to create hooks placed in GeneratorsByVersion, in order to modify the behavior of this library's NewGenerator function.
type GeneratorFactoryFunc ¶
GeneratorFactoryFunc implements GeneratorFactory with a function.
func (GeneratorFactoryFunc) NewGenerator ¶
func (fn GeneratorFactoryFunc) NewGenerator(version Version, o Options) (Generator, error)
type LeapSecondCalculator ¶
type LeapSecondCalculator interface {
LeapSecondsSinceUnixEpoch(seconds int64, includesLeapSeconds bool) int
}
LeapSecondCalculator is an interface for calculating the number of leap seconds by which Unix time differs from the number of SI seconds since 1970-01-01T00:00:00Z UTC.
Leap seconds cannot be predicted sooner than about six months or so ahead of time, so a proper implementation must source this data from the International Earth Rotation and Reference Systems Service (IERS), or from an organization which redistributes it in a timely manner such as IETF or IANA, and it must be updated regularly. On Linux hosts, this data is usually provided as part of your distribution's regularly updated timezone database. Other operating systems may vary.
type LeapSecondCalculatorDummy ¶ added in v0.3.0
type LeapSecondCalculatorDummy struct{}
LeapSecondCalculatorDummy falsely claims that there has never been a leap second. Although this is not actually true, many existing Version 1 UUID generators behave as though this is the case.
func (LeapSecondCalculatorDummy) LeapSecondsSinceUnixEpoch ¶ added in v0.3.0
func (LeapSecondCalculatorDummy) LeapSecondsSinceUnixEpoch(seconds int64, includesLeapSeconds bool) int
type LeapSecondCalculatorFixed ¶ added in v0.3.0
type LeapSecondCalculatorFixed struct{}
LeapSecondCalculatorFixed makes a best effort calculation of the number of leap seconds that have elapsed before a given time. The list of leap seconds is statically compiled into the library and is subject to updates.
In particular, although historical leap seconds never change once recorded, differences may arise between past computations of a given recent date and present computations if this library is updated between computations.
func (LeapSecondCalculatorFixed) LeapSecondsSinceUnixEpoch ¶ added in v0.3.0
func (LeapSecondCalculatorFixed) LeapSecondsSinceUnixEpoch(seconds int64, includesLeapSeconds bool) int
type Method ¶ added in v0.2.0
type Method uint
Method enumerates the Generator methods which do not need to be implemented.
const ( MethodNewUUID Method MethodNewHashUUID )
type Node ¶
type Node [6]byte
Node represents an EUI-48 network card hardware address, or something that has been formatted to look like one.
func GenerateNode ¶
GenerateNode returns the best available node identifier given the current host's EUI-48 and EUI-64 network addresses, or else it generates one at random as a fallback.
func (Node) IsGlobal ¶
IsGlobal returns true if the G/L bit is set to "G", meaning that it is globally unique a.k.a. "OUI ENFORCED".
As a special case, it returns false for the nil node identifier.
func (Node) IsLocal ¶
IsLocal returns true if the G/L bit is set to "L", meaning that it is locally defined a.k.a. "LOCALLY ADMINISTERED".
As a special case, it also returns true for the nil node identifier.
func (Node) IsMulticast ¶
IsMulticast returns true if the U/M bit is set to "M", meaning that it is a multicast EUI-48 address.
As a special case, it also returns true for the nil node identifier.
Multicast addresses are usually generated on-the-fly and are not unique to one host, so they are rarely the best choice for UUID uniqueness.
func (Node) IsUnicast ¶
IsUnicast returns true if the U/M bit is set to "U", meaning that it is a unicast EUI-48 address.
As a special case, it returns false for the nil node identifier.
type Operation ¶
type Operation uint
Operation enumerates the operations which can fail while initializing a Generator or generating a UUID.
const ( GenerateNodeOp Operation ClockStorageLoadOp ClockStorageStoreOp InitializeBlakeHashOp ReadRandomOp NetInterfacesOp )
type Options ¶ added in v0.3.0
type Options struct { // Node indicates the node identifier to use. The node identifier is // typically either a unique EUI-48 network hardware address associated // with the current host, or else a random 46-bit value modified to // look like a non-globally-unique EUI-48. // // Only time-based UUID generators use this field. If this field is // the zero value but a generator requires it, then the generator will // query the local host during generator initialization by using the // GenerateNode function provided by this library. // // If the caller wishes to guarantee uniqueness between multiple // Generator instances for the same UUID version, it is the // responsibility of the caller to verify that a globally unique Node // can be obtained for the current host, or else to generate a random // node identifier and then preserve it for re-use, e.g. by writing it // to a file so that it is not forgotten across reboots and program // restarts. // Node Node // TimeSource is a function which returns the current time. // // Only time-based UUID generators use this field. If this field is // nil but a generator requires it, then the built-in Go "time".Now // function is used instead. // TimeSource func() time.Time // LeapSecondCalculator provides the number of leap seconds by which // Unix time differs from the actual number of SI seconds since // 1970-01-01T00:00:00Z. // // Only V1 and V6 time-based UUID generators use this field. If this // field is required but nil, an instance of LeapSecondCalculatorDummy // will be used instead. The value is is needed to calculate the // RFC4122-correct timestamp values while generating V1 and V6 // time-based UUIDs. // LeapSecondCalculator LeapSecondCalculator // ClockStorage provides persistent storage for clock counters. // // Only time-based UUID generators use this field. If it is nil but a // generator requires it, then ClockStorageUnavailable is used instead. // This will degrade the uniqueness guarantees provided by those // generators; if the caller needs stronger guarantees, they must // provide their own ClockStorage instance that meets their // requirements. // ClockStorage ClockStorage // Namespace is the base UUID for namespacing data inputs when hashing. // // Only hash-based UUID generators use this field, but for those UUID // generators it is a mandatory field. Generator initialization will // fail if this field is not initialized to a valid UUID. // Namespace UUID // HashFactory is a callback to produce new instances of hash.Hash on demand. // // Only hash-based UUID generators for V8 UUIDs use this field, and for // that case the field is mandatory. V3 and V5 UUID generators ignore // this field and always use md5.New or sha1.New, respectively. // HashFactory func() hash.Hash // ForceRandomNode controls the behavior of GenerateNode when a node // identifier is required but Node is the zero value. // ForceRandomNode bool // RandomSource specifies a source of random bytes. // // Both random-based and time-based UUID generators use this field, // although the latter only use it to generate a node identifier if one // cannot otherwise be obtained. If this field is nil but a source of // random bytes is required, then "crypto/rand".Reader will be used // instead. // RandomSource io.Reader }
Options supplies options for generating UUID values.
type ParseProblem ¶
type ParseProblem uint
ParseProblem enumerates the types of problems which can be encountered while parsing strings as UUIDs.
const ( UnexpectedCharacter ParseProblem WrongVariant WrongTextLength WrongBinaryLength )
func (ParseProblem) Data ¶
func (enum ParseProblem) Data() EnumData
func (ParseProblem) FormatString ¶ added in v0.3.0
func (enum ParseProblem) FormatString() string
func (ParseProblem) GoString ¶
func (enum ParseProblem) GoString() string
func (ParseProblem) String ¶
func (enum ParseProblem) String() string
type TextUUID ¶ added in v0.2.0
type TextUUID struct {
UUID UUID
}
TextUUID is a wrapper type for UUID that SQL databases will store as a 36-character formatted string, instead of as a 16-byte raw binary value.
type UUID ¶
UUID represents a UUID. Only the RFC 4122 variant is supported.
func (UUID) Convert ¶ added in v0.4.0
func (uuid UUID) Convert(version Version, lsc LeapSecondCalculator) (UUID, error)
Convert returns a copy of this UUID which has been converted from its current UUID version to the given UUID version. Most version combinations are not possible. This method will return ErrVersionMismatch for such combinations.
The primary use for this method is to convert V1 UUIDs into V6 UUIDs and back, as this is the only pair for which bidirectional conversions exist. You can also convert V1/V6 into V7 unidirectionally, and you can convert absolutely any valid UUID into V8 unidirectionally.
Nil and Max are always returned unmodified.
Only V1 and V6 UUIDs make use of the LeapSecondCalculator argument, and only when converting to V7 UUIDs. If it is required but nil, then a LeapSecondCalculatorDummy will be used instead.
func (UUID) Decode ¶ added in v0.4.0
func (uuid UUID) Decode(lsc LeapSecondCalculator) Decoded
Decode breaks down this UUID into its component fields.
Only V1 and V6 UUIDs make use of the LeapSecondCalculator argument. If it is required but nil, then a LeapSecondCalculatorDummy will be used instead.
func (UUID) Domain ¶ added in v0.2.0
Domain returns the DCE domain of the UUID.
This value is only meaningful for valid version 2 UUIDs.
func (UUID) ID ¶ added in v0.2.0
Domain returns the DCE domain of the UUID.
This value is only meaningful for valid version 2 UUIDs.
func (UUID) IsValid ¶
IsValid returns true iff this UUID is a valid UUID according to the rules for the RFC 4122 variant format.
The nil UUID and the max UUID are *not* valid UUIDs according to this test.
func (UUID) MarshalBinary ¶ added in v0.2.0
MarshalBinary fulfills the "encoding".BinaryMarshaler interface.
func (UUID) MarshalJSON ¶ added in v0.2.0
MarshalJSON fulfills the "encoding/json".Marshaler interface.
func (UUID) MarshalText ¶ added in v0.2.0
MarshalText fulfills the "encoding".TextMarshaler interface.
func (*UUID) UnmarshalBinary ¶ added in v0.2.0
UnmarshalBinary fulfills the "encoding".BinaryUnmarshaler interface.
func (*UUID) UnmarshalJSON ¶ added in v0.2.0
UnmarshalJSON fulfills the "encoding/json".Unmarshaler interface.
func (*UUID) UnmarshalText ¶ added in v0.2.0
UnmarshalText fulfills the "encoding".TextUnmarshaler interface.