golang-yitisheng-server/server/common/id_utils.go

104 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package common
import (
"fmt"
"strconv"
"sync"
"time"
)
// IDGenerator 简单的 ID 生成器(类似 Snowflake
type IDGenerator struct {
mu sync.Mutex
lastTime int64
sequence int64
machineID int64
}
var (
defaultGenerator *IDGenerator
once sync.Once
)
// GetIDGenerator 获取默认生成器单例
func GetIDGenerator() *IDGenerator {
once.Do(func() {
defaultGenerator = &IDGenerator{
machineID: 1, // 默认机器 ID实际可从配置读取
}
})
return defaultGenerator
}
// NextID 生成下一个 64 位整数 ID
// 格式:时间戳(毫秒) + 机器ID + 序列号
func (g *IDGenerator) NextID() int64 {
g.mu.Lock()
defer g.mu.Unlock()
now := time.Now().UnixMilli()
if now == g.lastTime {
g.sequence = (g.sequence + 1) & 4095 // 12位序列号
if g.sequence == 0 {
// 序列号溢出,等待下一毫秒
for now <= g.lastTime {
now = time.Now().UnixMilli()
}
}
} else {
g.sequence = 0
}
g.lastTime = now
// 简单的位运算组合 ID
// 时间戳(41位) | 机器ID(10位) | 序列号(12位)
// 这里为了简单,直接返回时间戳+序列号的组合
// 如果需要严格的 long 类型且包含时间戳信息:
return now*10000 + g.sequence
}
// NextIDStr 生成字符串类型的 ID
func (g *IDGenerator) NextIDStr() string {
return strconv.FormatInt(g.NextID(), 10)
}
// GenerateLongID 全局辅助函数:生成 long 类型 ID
func GenerateLongID() int64 {
return GetIDGenerator().NextID()
}
// GenerateStringID 全局辅助函数:生成 string 类型 ID
func GenerateStringID() string {
return GetIDGenerator().NextIDStr()
}
// FormatTimestampToLong 将指定时间转为 long 格式 (yyyyMMddHHmmss)
func FormatTimestampToLong(t time.Time) int64 {
s := t.Format("20060102150405")
id, _ := strconv.ParseInt(s, 10, 64)
return id
}
// GenerateTimestampLongID 生成当前时间的 long 格式 ID (yyyyMMddHHmmss + 3位随机/序列)
func (g *IDGenerator) GenerateTimestampLongID() int64 {
g.mu.Lock()
defer g.mu.Unlock()
now := time.Now()
timestampStr := now.Format("20060102150405")
nowMs := now.UnixMilli()
if nowMs/1000 == g.lastTime/1000 {
g.sequence = (g.sequence + 1) & 999
} else {
g.sequence = 0
}
g.lastTime = nowMs
idStr := fmt.Sprintf("%s%03d", timestampStr, g.sequence)
id, _ := strconv.ParseInt(idStr, 10, 64)
return id
}