• 生成全世界唯一的uuid(golang实现)


    思路

    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
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    输出:

    [37 184 0 78 1 158 184 47 99 31 44 217 1]
    
    • 1

    处理结果:
    这里程序生成的是一个长度为13的byte数组,具体如何把这个数组转成一个用户友好的字符串方法有很多,比如6字节6字节为一个单位映射成字符。具体不作实现。

  • 相关阅读:
    @data注解的作用
    ansible
    web3 前端dapp从redux过滤出 (我创建与别人创建)正在执行的订单 并展示在Table上
    自定义实现:头像上传View
    如何基于原名称批量重命名(格式化)文件(夹)名
    排序算法··
    K8S原来如此简单(八)ServiceAccount+RBAC
    谷歌关于视频无法自动播放问题
    2022pycharm:虚拟环境的启用与删除
    cocos2dx 3D物理相关知识点汇总
  • 原文地址:https://blog.csdn.net/qq_31618549/article/details/126822663