Source file src/uuid/uuid.go
1 // Copyright 2026 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package uuid provides support for generating and manipulating UUIDs. 6 // 7 // See [RFC 9562] for details. 8 // 9 // Random components of new UUIDs are generated with a 10 // cryptographically secure random number generator. 11 // 12 // UUIDs may be generated using various algorithms. 13 // The [New] function returns a new UUID generated using 14 // an algorithm suitable for most purposes. 15 // 16 // [RFC 9562]: https://www.rfc-editor.org/rfc/rfc9562.html 17 package uuid 18 19 import ( 20 "bytes" 21 "cmp" 22 "crypto/rand" 23 "encoding/binary" 24 "encoding/hex" 25 "errors" 26 "sync" 27 "time" 28 ) 29 30 // A UUID is a Universally Unique Identifier as specified in RFC 9562. 31 // 32 // UUIDs are comparable, such as with the == operator. 33 type UUID [16]byte 34 35 // Parse returns the UUID represented by s. 36 // 37 // It accepts strings in the following forms: 38 // 39 // f81d4fae-7dec-11d0-a765-00a0c91e6bf6 40 // {f81d4fae-7dec-11d0-a765-00a0c91e6bf6} 41 // urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 42 // f81d4fae7dec11d0a76500a0c91e6bf6 43 // 44 // Alphabetic characters in the hexadecimal digits may be any case. 45 func Parse(s string) (UUID, error) { 46 var u UUID 47 err := u.UnmarshalText([]byte(s)) 48 return u, err 49 } 50 51 // MustParse returns the UUID represented by s. 52 // 53 // It panics if s is not a valid string representation of a UUID as defined by [Parse]. 54 func MustParse(s string) UUID { 55 u, err := Parse(s) 56 if err != nil { 57 panic(err) 58 } 59 return u 60 } 61 62 // New returns a new UUID. 63 // 64 // Programs which do not have a need for a specific UUID generation algorithm should use New. 65 // At this time, New is equivalent to [NewV4]. 66 func New() UUID { 67 return NewV4() 68 } 69 70 // Nil returns the Nil UUID 00000000-0000-0000-0000-000000000000. 71 // 72 // The Nil UUID is defined in [Section 5.9 of RFC 9562]. 73 // Note that this is not the same as the Go value nil. 74 // 75 // [Section 5.9 of RFC 9562]: https://www.rfc-editor.org/rfc/rfc9562#section-5.9 76 func Nil() UUID { 77 return UUID{} 78 } 79 80 // Max returns the Max UUID ffffffff-ffff-ffff-ffff-ffffffffffff. 81 // 82 // The Max UUID is defined in [Section 5.10 of RFC 9562]. 83 // 84 // [Section 5.10 of RFC 9562]: https://www.rfc-editor.org/rfc/rfc9562#section-5.10 85 func Max() UUID { 86 return UUID{ 87 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 88 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 89 } 90 } 91 92 // String returns the string representation of u. 93 // 94 // It uses the lowercase hex-and-dash representation defined in RFC 9562. 95 func (u UUID) String() string { 96 b, _ := u.MarshalText() 97 return string(b) 98 } 99 100 // MarshalText implements the [encoding.TextMarshaler] interface. 101 // The encoding is the same as returned by [UUID.String] 102 func (u UUID) MarshalText() ([]byte, error) { 103 return u.AppendText(make([]byte, 0, 36)) 104 } 105 106 // AppendText implements the [encoding.TextAppender] interface. 107 // The encoding is the same as returned by [UUID.String] 108 func (u UUID) AppendText(b []byte) ([]byte, error) { 109 off := len(b) 110 b = append(b, "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"...) 111 dst := b[off:] 112 hex.Encode(dst[0:8], u[0:4]) 113 hex.Encode(dst[9:13], u[4:6]) 114 hex.Encode(dst[14:18], u[6:8]) 115 hex.Encode(dst[19:23], u[8:10]) 116 hex.Encode(dst[24:36], u[10:16]) 117 return b, nil 118 } 119 120 var errInvalid = errors.New("invalid uuid") 121 122 // UnmarshalText implements the [encoding.TextUnmarshaler] interface. 123 // The UUID is expected in a form accepted by [Parse]. 124 func (u *UUID) UnmarshalText(b []byte) error { 125 var dst UUID 126 switch len(b) { 127 case len("urn:uuid:") + 36: 128 // urn:uuid:00000000-0000-0000-0000-000000000000 129 b = bytes.TrimPrefix(b, []byte("urn:uuid:")) 130 case 2 + 36: 131 // {00000000-0000-0000-0000-000000000000} 132 b = bytes.TrimPrefix(b, []byte("{")) 133 b = bytes.TrimSuffix(b, []byte("}")) 134 case 32: 135 // 00000000000000000000000000000000 136 if _, err := hex.Decode(dst[:], b); err != nil { 137 return errInvalid 138 } 139 *u = dst 140 return nil 141 } 142 // 00000000-0000-0000-0000-000000000000 143 if len(b) != 36 { 144 return errInvalid 145 } 146 if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { 147 return errInvalid 148 } 149 if _, err := hex.Decode(dst[0:4], b[0:8]); err != nil { 150 return errInvalid 151 } 152 if _, err := hex.Decode(dst[4:6], b[9:13]); err != nil { 153 return errInvalid 154 } 155 if _, err := hex.Decode(dst[6:8], b[14:18]); err != nil { 156 return errInvalid 157 } 158 if _, err := hex.Decode(dst[8:10], b[19:23]); err != nil { 159 return errInvalid 160 } 161 if _, err := hex.Decode(dst[10:16], b[24:36]); err != nil { 162 return errInvalid 163 } 164 *u = dst 165 return nil 166 } 167 168 // Compare compares the UUID u with v. 169 // If u is before v, it returns -1. 170 // If u is after v, it returns +1. 171 // If they are the same, it returns 0. 172 // 173 // Compare uses the big-endian byte order defined in 174 // [Section 6.11 of RFC 9562] for sorting. 175 // 176 // [Section 6.11 of RFC 9562]: https://www.rfc-editor.org/rfc/rfc9562#section-6.11 177 func (u UUID) Compare(v UUID) int { 178 for i := range u { 179 if c := cmp.Compare(u[i], v[i]); c != 0 { 180 return c 181 } 182 } 183 return 0 184 } 185 186 // NewV4 returns a new version 4 UUID. 187 // 188 // Version 4 UUIDs contain 122 bits of random data. 189 func NewV4() UUID { 190 var u UUID 191 rand.Read(u[:]) 192 u.setVersion(4) 193 u.setVariant(0b10) 194 return u 195 } 196 197 var ( 198 v7mu sync.Mutex 199 v7lastSecs uint64 200 v7lastTimestamp uint64 201 ) 202 203 // NewV7 returns a new version 7 UUID. 204 // 205 // Version 7 UUIDs contain a timestamp in the most significant 48 bits, 206 // and at least 62 bits of random data. 207 // 208 // NewV7 always returns UUIDs which sort in increasing order, 209 // except when the system clock moves backwards. 210 func NewV7() UUID { 211 // UUIDv7 is defined in RFC 9562 section 5.7 as: 212 // 213 // 0 1 2 3 214 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 215 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 216 // | unix_ts_ms | 217 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 218 // | unix_ts_ms | ver | rand_a | 219 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 220 // |var| rand_b | 221 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 222 // | rand_b | 223 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 224 // 225 // We store a 12 bit sub-millisecond timestamp fraction in the rand_a section, 226 // as optionally permitted by the RFC. 227 v7mu.Lock() 228 229 // Generate our 60-bit timestamp: 48 bits of millisecond-resolution, 230 // followed by 12 bits of 1/4096-millisecond resolution. 231 now := time.Now() 232 secs := uint64(now.Unix()) 233 nanos := uint64(now.Nanosecond()) 234 msecs := nanos / 1000000 235 frac := nanos - (1000000 * msecs) 236 timestamp := (1000*secs + msecs) << 12 // ms shifted into position 237 timestamp += (frac * 4096) / 1000000 // ns converted to 1/4096-ms units 238 239 if v7lastSecs > secs { 240 // Time has gone backwards. 241 // This presumably indicates the system clock has changed. 242 // Ignore previously-generated UUIDs. 243 } else if timestamp <= v7lastTimestamp { 244 // This timestamp is the same as a previously-generated UUID. 245 // To preserve the property that we generate UUIDs in order, 246 // use a timestamp 1/4096 millisecond later than the most recently 247 // generated UUID. 248 timestamp = v7lastTimestamp + 1 249 } 250 251 v7lastSecs = secs 252 v7lastTimestamp = timestamp 253 v7mu.Unlock() 254 255 // Insert a gap for the 4 bits of the ver field into the timestamp. 256 hibits := ((timestamp << 4) & 0xffff_ffff_ffff_0000) | (timestamp & 0x0ffff) 257 258 var u UUID 259 binary.BigEndian.PutUint64(u[0:8], hibits) 260 rand.Read(u[8:]) 261 u.setVersion(7) 262 u.setVariant(0b10) 263 264 return u 265 } 266 267 func (u *UUID) setVersion(version byte) { 268 u[6] = (u[6] & 0b0000_1111) | (version << 4) 269 } 270 271 func (u *UUID) setVariant(variant byte) { 272 u[8] = (u[8] & 0b0011_1111) | (variant << 6) 273 } 274