generator.go (809B)
1 package snowflakes 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 type Generator struct { 9 sync.Mutex 10 11 NodeID uint64 12 Epoch int64 13 14 lastGen int64 15 sequence uint64 16 } 17 18 func New(id uint64) *Generator { 19 return &Generator{ 20 NodeID: id, 21 } 22 } 23 24 func NewWithEpoch(id uint64, epoch time.Time) *Generator { 25 return &Generator{ 26 NodeID: id, 27 Epoch: epoch.UnixMilli(), 28 } 29 } 30 31 func (g *Generator) Next() uint64 { 32 g.Lock() 33 defer g.Unlock() 34 35 now := time.Now().UnixMilli() - g.Epoch 36 if now < 0 { 37 panic("system time can not be older than epoch") 38 } 39 40 // "now" can be past, but we won't wait. 41 42 if g.lastGen < now { 43 g.lastGen = now 44 g.sequence = 0 45 } else if g.sequence == 0x0FFF { 46 g.lastGen++ 47 g.sequence = 0 48 } else { 49 g.sequence++ 50 } 51 52 return uint64(g.lastGen)&0x1FFFFFFFFFF<<22 + g.NodeID&0x03FF<<12 + g.sequence&0x0FFF 53 }