package helpers import ( "crypto/rand" "encoding/binary" "fmt" "time" ) const ( // UUID v7 格式常量. uuidRandomBytesSize = 10 // UUID中随机字节部分的大小 uuidVersion7 = 0x7000 // UUID v7的版本位 uuidVariant = 0x80 // UUID的变体位 uuidTimeMask = 0xFFFF // 时间戳掩码 uuidTimeShift = 16 // 时间戳位移 uuidVariantMask = 0x3F // 变体掩码 ) // NewUUIDv7 生成 UUID v7 并去除连字符. func NewUUIDv7() string { // 获取当前时间戳(Unix 毫秒时间戳) now := time.Now().UnixMilli() // 生成随机字节 randBytes := make([]byte, uuidRandomBytesSize) _, err := rand.Read(randBytes) if err != nil { // 如果随机数生成失败,使用时间戳加一些伪随机值作为备选方案 return fmt.Sprintf("%016x%016x", now, time.Now().UnixNano()) } // 版本和变体位 // 版本: 0x7 (0111) << 12 // 变体: 0x2 (10) << 6 versionVariant := uint16(uuidVersion7 | uuidVariant) // 构建 UUID 字节数组 var uuid [16]byte // 时间戳低32位 (4 bytes) //nolint:gosec // UUID格式要求的类型转换 binary.BigEndian.PutUint32(uuid[0:4], uint32(now>>uuidTimeShift)) // 时间戳中16位 + 版本 (2 bytes) //nolint:gosec // UUID格式要求的类型转换 binary.BigEndian.PutUint16(uuid[4:6], uint16(now&uuidTimeMask)) // 时间戳高16位 + 变体 (2 bytes) binary.BigEndian.PutUint16(uuid[6:8], versionVariant) // 随机数部分 (8 bytes) copy(uuid[8:16], randBytes[:8]) // 设置变体位 (第8个字节的高两位为10) uuid[8] = (uuid[8] & uuidVariantMask) | uuidVariant // 转换为十六进制字符串并去除连字符 return fmt.Sprintf("%08x%04x%04x%04x%08x%04x", binary.BigEndian.Uint32(uuid[0:4]), binary.BigEndian.Uint16(uuid[4:6]), binary.BigEndian.Uint16(uuid[6:8]), binary.BigEndian.Uint16(uuid[8:10]), binary.BigEndian.Uint32(uuid[10:14]), binary.BigEndian.Uint16(uuid[14:16])) }