48位mac地址+16位进程号+32位时间戳+8位时间戳内偏移量
48位mac地址保证了同一机器上生成的uuid不会和其他机器冲突
16位进程号保证了同一机器上的不同进程生成的uuid不冲突
32位时间戳保证了同一进程上不同时间生成的uuid不冲突
8位时间戳内偏移量保证了同一进程同一时间生成的uuid不唯一
这样子,我们的uuid就是全世界唯一的了
package main
import (
"fmt"
"net"
"os"
"strings"
"time"
)
var lastTimestamp int64 = time.Now().Unix()
var count byte = 0
func main() {
fmt.Println(getUUIDBytes())
}
func getUUIDBytes() []byte {
//最终存放的字节数组
uuidBytes := make([]byte, 13)
offset := 0
copy(uuidBytes[offset:], getPidBytes())
offset += 2
copy(uuidBytes[offset:], getLocalMacBytes())
offset += 6
copy(uuidBytes[offset:], getTimestampBytes())
offset += 4
copy(uuidBytes[offset:], getCountInTimeBytes())
return uuidBytes
}
//16进制字符转数字
func hexCharToNum(hex byte) byte {
if hex >= 'a' {
return hex - 'a' + 10
}
if hex >= 'A' {
return hex - 'A' + 10
}
return hex - '0'
}
// 获取时间戳内偏移量
func getCountInTimeBytes() []byte {
bytes := make([]byte, 1)
now := time.Now().Unix()
if now == lastTimestamp {
count++
} else {
count = 0
}
lastTimestamp = now
bytes[0] = count
return bytes
}
// 获取时间戳的byte[]数组
func getTimestampBytes() []byte {
bytes := make([]byte, 4)
timestamp := uint32(time.Now().Unix())
for i := 3; i >= 0; i-- {
bytes[i] = byte(timestamp)
timestamp >>= 8
}
return bytes
}
// 获取本程序的进程号byte[]数组
func getPidBytes() []byte {
bytes := make([]byte, 2)
pid := uint16(os.Getpid())
bytes[0] = byte(pid >> 8)
bytes[1] = byte(pid)
return bytes
}
// 获取本机的MAC地址byte[]数组
func getLocalMacBytes() []byte {
bytes := make([]byte, 6)
interfaces, err := net.Interfaces()
if err != nil {
return nil
}
macString := ""
for _, inter := range interfaces {
macString = inter.HardwareAddr.String()
break
}
if macString == "" {
return nil
}
macStrSplits := strings.Split(macString, ":")
for index, split := range macStrSplits {
bytes[index] = hexCharToNum(split[0])<<4 + hexCharToNum(split[1])
}
return bytes
}
输出:
[37 184 0 78 1 158 184 47 99 31 44 217 1]
处理结果:
这里程序生成的是一个长度为13的byte数组,具体如何把这个数组转成一个用户友好的字符串方法有很多,比如6字节6字节为一个单位映射成字符。具体不作实现。