package snowflake import ( "apsClient/pkg/logx" "errors" "fmt" "hash/fnv" "net" "strconv" "sync" "time" ) var idGenerater *IdWorker func init() { // 使用 LookupIP 获取主机的 IP 地址列表 // 获取本机所有网络接口 interfaces, err := net.Interfaces() if err != nil { logx.Errorf("snowflake InitWithIP error:%v", err) return } var ip string // 遍历所有网络接口 for _, iface := range interfaces { // 排除一些特殊的接口,例如 loopback 接口 if iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagLoopback == 0 { // 获取接口的所有地址 addrs, err := iface.Addrs() if err != nil { logx.Errorf("snowflake InitWithIP error:%v", err) continue } // 遍历接口的所有地址 for _, addr := range addrs { // 检查地址类型是否是 IP 地址 if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { // 判断 IP 地址的版本是 IPv4 还是 IPv6 if ipNet.IP.To4() != nil { fmt.Printf("IPv4 Address: %s\n", ipNet.IP.String()) if ipNet.IP.String() != "127.0.0.1" { ip = ipNet.IP.String() goto getIpOK } } else { fmt.Printf("IPv6 Address: %s\n", ipNet.IP.String()) } } } } } getIpOK: if ip == "" { logx.Errorf("snowflake InitWithIP can not find Ip") return } ipNumber, err := ipToNumber(ip) if err != nil { logx.Errorf("snowflake can not generate, init error, ip to number error :%v", err) panic(fmt.Sprintf("snowflake can not generate, init error, ip to number error :%v", err)) } idGenerater, err = NewIdWorker(ipNumber) if err != nil { logx.Errorf("snowflake can not generate, init error :%v", err) panic(fmt.Sprintf("snowflake can not generate, init error :%v", err)) } } func ipToNumber(ip string) (int64, error) { // 将 IP 地址字符串解析为 net.IP 类型 parsedIP := net.ParseIP(ip) if parsedIP == nil { return 0, fmt.Errorf("invalid IP address:%v", ip) } // 使用 FNV-1a 散列算法计算哈希值 hash := fnv.New32a() hash.Write(parsedIP) return int64(hash.Sum32() % 1024), nil // 取余数确保结果在 1 到 1023 之间 } const ( CEpoch = 1474802888000 CWorkerIdBits = 10 // Num of WorkerId Bits CSenquenceBits = 12 // Num of Sequence Bits CWorkerIdShift = 12 CTimeStampShift = 22 CSequenceMask = 0xfff // equal as getSequenceMask() CMaxWorker = 0x3ff // equal as getMaxWorkerId() ) type IdWorker struct { workerId int64 lastTimeStamp int64 sequence int64 maxWorkerId int64 lock *sync.Mutex } func NewIdWorker(workerId int64) (iw *IdWorker, err error) { iw = new(IdWorker) iw.maxWorkerId = getMaxWorkerId() if workerId > iw.maxWorkerId || workerId < 0 { return nil, errors.New("worker not fit") } iw.workerId = workerId iw.lastTimeStamp = -1 iw.sequence = 0 iw.lock = new(sync.Mutex) return iw, nil } func getMaxWorkerId() int64 { return -1 ^ -1<> CWorkerIdShift) & CMaxWorker ts = (id >> CTimeStampShift) + CEpoch t = time.Unix(ts/1000, (ts%1000)*1000000) return } func GenerateID() int64 { start: id, err := idGenerater.NextId() if err != nil { goto start } return id } func GenerateIdStr() string { start: id, err := idGenerater.NextId() if err != nil { goto start } return strconv.FormatInt(id, 10) }