package uuid import ( "unsafe" "github.com/google/uuid" ) const ( letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" MIN_LENGTH = 2 // 最小长度为2的原因是Go中整型长度最大为64位,而UUID v4是128位长,所以最小长度为2。 MAX_LENGTH = 128 ) // 将一个字节拆分成8个比特位,并以一个8位长字节数组输出。 func breakByte(b byte) []byte { bytes := make([]byte, 8) for i := byte(0); i < 8; i++ { mask := byte(0x1) << (7 - i) bytes[i] = (b & mask) >> (7 - i) } return bytes } // 根据UUID v4生成一个指定长度的短UUID字符串。 func ShortUUID(length uint) string { var uuidLength uint if length < MIN_LENGTH { uuidLength = MIN_LENGTH } else if length > MAX_LENGTH { uuidLength = MAX_LENGTH } else { uuidLength = length } // UUID是一个16字节长的字节数组,每个字节都可以拆分成8个比特位,共128比特位。 newUUID := uuid.New() uuidBits := make([]byte, 0) for _, b := range newUUID[:] { uuidBits = append(uuidBits, breakByte(b)...) } var partitionLength uint = 0 if 128%uuidLength == 0 { partitionLength = 128 / uuidLength } else { partitionLength = 128/uuidLength + 1 } var paritionedUUID = make([][]byte, uuidLength) for i := uint(0); i < uuidLength; i++ { if i != uuidLength-1 { paritionedUUID[i] = uuidBits[i*partitionLength : (i+1)*partitionLength] } else { paritionedUUID[i] = uuidBits[i*partitionLength:] } } result := make([]byte, uuidLength) for i := uint(0); i < uuidLength; i++ { var assembledRune uint64 = 0 for j := uint(0); j < uint(len(paritionedUUID[i])); j++ { assembledRune |= uint64(paritionedUUID[i][j]) << (partitionLength - j - 1) } result[i] = letters[assembledRune%uint64(len(letters))] } return *(*string)(unsafe.Pointer(&result)) }