package snowflake import ( "errors" "strconv" "sync" "time" ) const ( CEpoch = 1474802888000 CWorkerIdBits = 10 // Num of WorkerId Bits CSenquenceBits = 12 // Num of Sequence Bits CWorkerIdShift = 12 CTimeStampShift = 22 CSequenceMask = 0xfff // equal as getSequenceMask() CMaxWorker = 0x3ff // equal as getMaxWorkerId() ) type IdWorker struct { workerId int64 lastTimeStamp int64 sequence int64 maxWorkerId int64 lock *sync.Mutex } func NewIdWorker(workerId int64) (iw *IdWorker, err error) { iw = new(IdWorker) iw.maxWorkerId = getMaxWorkerId() if workerId > iw.maxWorkerId || workerId < 0 { return nil, errors.New("worker not fit") } iw.workerId = workerId iw.lastTimeStamp = -1 iw.sequence = 0 iw.lock = new(sync.Mutex) return iw, nil } func getMaxWorkerId() int64 { return -1 ^ -1<> CWorkerIdShift) & CMaxWorker ts = (id >> CTimeStampShift) + CEpoch t = time.Unix(ts/1000, (ts%1000)*1000000) return } var idGenerater, _ = NewIdWorker(0) func GenerateId() int64 { start: id, err := idGenerater.NextId() if err != nil { goto start } return id } func GenerateIdStr() string { start: id, err := idGenerater.NextId() if err != nil { goto start } return strconv.FormatInt(id, 10) }