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

90 lines
1.6 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 (
"strconv"
"sync"
"time"
)
// IDGenerator 简单的 ID 生成器(类似 Snowflake
type IDGenerator struct {
mu sync.RWMutex
lastTime int64
sequence int64
machineID int64
}
var (
defaultGenerator *IDGenerator
once sync.Once
)
// GetIDGenerator 获取默认生成器单例
func GetIDGenerator() *IDGenerator {
once.Do(func() {
defaultGenerator = &IDGenerator{
machineID: 1,
}
})
return defaultGenerator
}
// Lazy initialize on first access
func getInstance() *IDGenerator {
if defaultGenerator == nil {
once.Do(func() {
defaultGenerator = &IDGenerator{
machineID: 1,
}
})
}
return defaultGenerator
}
// GenerateStringID 全局辅助函数:生成 string 类型 ID
func GenerateStringID() string {
gen := getInstance()
if gen == nil {
// Fallback: create new instance if singleton fails
gen = &IDGenerator{machineID: 1}
}
return gen.NextIDStr()
}
// GenerateLongID 全局辅助函数:生成 long 类型 ID
func GenerateLongID() int64 {
gen := getInstance()
if gen == nil {
gen = &IDGenerator{machineID: 1}
}
return gen.NextID()
}
// NextID 生成下一个 64 位整数 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
if g.sequence == 0 {
for now <= g.lastTime {
now = time.Now().UnixMilli()
}
}
} else {
g.sequence = 0
}
g.lastTime = now
return now*10000 + g.sequence
}
// NextIDStr 生成字符串类型的 ID
func (g *IDGenerator) NextIDStr() string {
id := g.NextID()
return strconv.FormatInt(id, 10)
}