12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- package utils
- import (
- "fmt"
- "strconv"
- "sync"
- "time"
- )
- type Snowflake struct {
- epoch int64
- timestamp int64
- dataCenter int64
- workerId int64
- sequence int64
- mutex sync.Mutex
- maxSequence int64
- }
- const (
- epochShift = 22
- dataCenterShift = 12
- workerIdShift = 10
- sequenceShift = 0
- sequenceMask = -1 ^ (-1 << sequenceShift)
- maxWorkerId = -1 ^ (-1 << workerIdShift)
- maxDataCenter = -1 ^ (-1 << dataCenterShift)
- )
- func NewSnowflake(epoch int64, dataCenter, workerId int64) (*Snowflake, error) {
- if dataCenter > maxDataCenter || workerId > maxWorkerId {
- return nil, fmt.Errorf("dataCenter or workerId exceeds limit")
- }
- return &Snowflake{
- epoch: epoch,
- dataCenter: dataCenter,
- workerId: workerId,
- maxSequence: -1 ^ (-1 << sequenceShift),
- }, nil
- }
- func (s *Snowflake) NextID() int64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- currentTimestamp := time.Now().UnixNano() / 1e6
- if s.timestamp == currentTimestamp {
- s.sequence = (s.sequence + 1) & sequenceMask
- if s.sequence == 0 {
- currentTimestamp = s.waitNextTime(currentTimestamp)
- }
- } else {
- s.sequence = 0
- }
- s.timestamp = currentTimestamp
- id := ((currentTimestamp - s.epoch) << epochShift) |
- (s.dataCenter << dataCenterShift) |
- (s.workerId << workerIdShift) |
- s.sequence
- return id
- }
- func (s *Snowflake) waitNextTime(currentTimestamp int64) int64 {
- for currentTimestamp <= s.timestamp {
- currentTimestamp = time.Now().UnixNano() / 1e6
- }
- return currentTimestamp
- }
- var snowflake, _ = NewSnowflake(time.Now().UnixNano()/1e6, 1, 1)
- func NextId() int64 {
- return snowflake.NextID()
- }
- func NextIdStr() string {
- return strconv.FormatInt(NextId(), 10)
- }
|