package uuidv7 import ( "crypto/rand" "encoding/hex" "fmt" "strings" "sync" "time" ) const ( epoch = 1645566142222 // 自定义纪元:2022-02-22 22:22:22.222 UTC nodeBits = 5 // 主机编号容量为0~32 sequenceBits = 18 // 每毫秒生成序列号最大为2^18-1,即262144个 maxNodeID = (1 << nodeBits) - 1 maxSequence = (1 << sequenceBits) - 1 timestampShift = nodeBits + sequenceBits nodeShift = sequenceBits ) type UUIDv7Generator struct { locker sync.Mutex nodeID int64 lastTime int64 sequence int64 } type UUIDv7Components struct { Timestamp int64 // 毫秒时间戳(相对于自定义纪元) NodeID int64 // 5位节点ID Sequence int64 // 18位序列号 Version int // 版本号(应为7) Variant int // 变体(应为2,表示10xx) RawBytes [16]byte // 原始字节 } var generatorInstance *UUIDv7Generator // 获取UUIDv7生成器实例。如果实例尚未初始化,则返回错误。 func Generator() (*UUIDv7Generator, error) { if generatorInstance == nil { return nil, &UUIDv7GeneratorNotInitializedError{} } return generatorInstance, nil } // 指定一个主机编号,并完成UUIDv7生成器的初始化。如果主机编号超出范围,则返回错误。 func Initialize(hostSerial int64) error { if hostSerial < 0 || hostSerial > maxNodeID { return &UUIDv7NodeIDExceededError{} } generatorInstance = &UUIDv7Generator{ nodeID: hostSerial, lastTime: epoch, } return nil } // 获取当前时间对应的新纪元毫秒时间戳。 func (g *UUIDv7Generator) Now() int64 { return time.Now().UnixMilli() - epoch } // 按顺序生成一个UUIDv7序号组件。 func (g *UUIDv7Generator) Next() UUIDv7Components { g.locker.Lock() defer g.locker.Unlock() now := g.Now() if now < g.lastTime { // 防止时间回拔的情况,发生回拔时,直接使用上一次的时间戳 now = g.lastTime } if now == g.lastTime { g.sequence++ if g.sequence > maxSequence { time.Sleep(time.Millisecond) now = g.Now() g.sequence = 0 } } else { g.sequence = 0 } g.lastTime = now return UUIDv7Components{ Timestamp: now, NodeID: g.nodeID, Sequence: g.sequence, Version: 7, Variant: 2, } } // 读取随机字节 func (c *UUIDv7Components) readRandom(bytes []byte) error { _, err := rand.Read(bytes) return err } // 获取UUIDv7原始字节数组 func (c *UUIDv7Components) Bytes() [16]byte { // 构造 UUID var uuid [16]byte // 时间戳(48 位) timestamp := uint64(c.Timestamp) << timestampShift seqAndNode := (uint64(c.Sequence) << nodeShift) | uint64(c.NodeID) // 写入高位时间戳 uuid[0] = byte(timestamp >> 56) uuid[1] = byte(timestamp >> 48) uuid[2] = byte(timestamp >> 40) uuid[3] = byte(timestamp >> 32) uuid[4] = byte(timestamp >> 24) uuid[5] = byte(timestamp >> 16) // 写入低位时间戳 + 版本号(4 位) uuid[6] = byte((timestamp >> 8) | 0x70) // version 7 uuid[7] = byte(timestamp) // 写入 seq + node uuid[8] = byte((seqAndNode >> 16) | 0x80) // variant 10xx uuid[9] = byte(seqAndNode >> 8) uuid[10] = byte(seqAndNode) // 剩余位全为 0(可扩展为更多节点 ID 或随机数) randomBytes := make([]byte, 5) if err := c.readRandom(randomBytes); err != nil { // 如果随机数生成失败,使用时间相关值作为后备 t := time.Now().UnixNano() randomBytes[0] = byte(t) randomBytes[1] = byte(t >> 8) randomBytes[2] = byte(t >> 16) randomBytes[3] = byte(t >> 24) randomBytes[4] = byte(c.Sequence) } copy(uuid[11:16], randomBytes) return uuid } // 获取UUIDv7字符串 func (c *UUIDv7Components) String() string { uuid := c.Bytes() return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:16]) } // 对解析后的UUIDv7进行比较,按照时间戳、序列号、节点ID进行排序 func CompareUUIDv7(a, b *UUIDv7Components) int { if a.Timestamp > b.Timestamp { return 1 } if a.Timestamp < b.Timestamp { return -1 } if a.Sequence > b.Sequence { return 1 } if a.Sequence < b.Sequence { return -1 } if a.NodeID > b.NodeID { return -1 } if a.NodeID < b.NodeID { return 1 } return 0 } // 与另一个UUIDv7进行比较,按照时间戳、序列号、节点ID进行排序 func (c *UUIDv7Components) Compare(b *UUIDv7Components) int { return CompareUUIDv7(c, b) } // ParseUUIDv7FromBytes 从字节数组解析 UUIDv7 func ParseUUIDv7FromBytes(data [16]byte) (*UUIDv7Components, error) { // 提取时间戳(前48位) timestamp := (int64(data[0]) << 40) | (int64(data[1]) << 32) | (int64(data[2]) << 24) | (int64(data[3]) << 16) | (int64(data[4]) << 8) | int64(data[5]) // 提取版本号(第6字节的高4位) version := int(data[6] >> 4) // 提取变体(第8字节的高2位) variant := int(data[8] >> 6) // 提取序列号和节点ID // 第8字节的低2位 + 第9字节 + 第10字节的高3位组成23位 seqAndNode := (int64(data[8]&0x3F) << 16) | // 第8字节低6位 (int64(data[9]) << 8) | // 第9字节 int64(data[10]) // 第10字节 // 分离序列号(高18位)和节点ID(低5位) sequence := seqAndNode >> 5 nodeID := seqAndNode & 0x1F return &UUIDv7Components{ Timestamp: timestamp, NodeID: nodeID, Sequence: sequence, Version: version, Variant: variant, RawBytes: data, }, nil } // ParseUUIDv7FromString 从字符串解析 UUIDv7 func ParseUUIDv7FromString(uuidStr string) (*UUIDv7Components, error) { // 移除连字符并验证长度 cleanStr := strings.ReplaceAll(uuidStr, "-", "") if len(cleanStr) != 32 { return nil, fmt.Errorf("无效的UUIDv7字符串长度") } // 解码十六进制字符串 bytes, err := hex.DecodeString(cleanStr) if err != nil { return nil, fmt.Errorf("无效的UUIDv7字符串格式: %v", err) } // 转换为数组 var uuidBytes [16]byte copy(uuidBytes[:], bytes) return ParseUUIDv7FromBytes(uuidBytes) }