接口设计
顾名思义id生成器的只需要一个接口,这个接口就是获取ID
// ID生成器的接口类型。 type IdGenerator interface { GetUint32() uint32 // 获得一个uint32类型的ID。 }
具体实现
这里可以先简要的介绍32位的id生成器如何生成。首先需要一个标记当前分配的ID,ID最大值,还有锁-保证并发ID不重复。
结构体如下:
// ID生成器的实现类型。 type cyclicIdGenerator struct { sn uint32 // 当前的ID。 ended bool // 前一个ID是否已经为其类型所能表示的最大值。 mutex sync.Mutex // 互斥锁。 }
具体实现函数如下方:
// 创建ID生成器。 func NewIdGenerator() IdGenerator { return &cyclicIdGenerator{} } func (gen *cyclicIdGenerator) GetUint32() uint32 { gen.mutex.Lock() defer gen.mutex.Unlock() if gen.ended { defer func() { gen.ended = false }() gen.sn = 0 return gen.sn } id := gen.sn if id < math.MaxUint32 { gen.sn++ } else { gen.ended = true } return id }
扩展讲解
现在我们可以借助32位的ID生成器,扩展为64位的ID生成器。其原理类似环形操作,仔细思考,64位是32位的两倍,所以我们可以基数个使用时候+基本数字最大值。偶数使用时候我们可以直接用32位返回值。
// ID生成器的实现类型2。 type cyclicIdGenerator2 struct { base cyclicIdGenerator // 基本的ID生成器。 cycleCount uint64 // 基于uint32类型的取值范围的周期计数。 } func (gen *cyclicIdGenerator2) GetUint64() uint64 { var id64 uint64 if gen.cycleCount%2 == 1 { id64 += math.MaxUint32 } id32 := gen.base.GetUint32() if id32 == math.MaxUint32 { gen.cycleCount++ } id64 += uint64(id32) return id64 }