104 lines
2.3 KiB
Go
104 lines
2.3 KiB
Go
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
|
||
}
|