package utils import ( "crypto/rand" "encoding/base64" "errors" "fmt" "sync" "time" ) const ( objectIDLen int = 24 ) var Idg, _ = NewDefaultIdGenerator(0) func GetShortObjectID(objectID string) (string, error) { length := len(objectID) if len(objectID) != objectIDLen { err := errors.New(fmt.Sprintf("Invalid ObjectId: length=%d", length)) return "", err } shortID := objectID[0:8] + objectID[18:] return shortID, nil } func AppIDAndSequence(appID string, sequence int) string { return fmt.Sprintf("%s_%d", appID, sequence) } func BuildRandomURLEncString(length int) (string, error) { b := make([]byte, length) if _, err := rand.Read(b); err != nil { return "", err } // url-safe no padding return base64.RawURLEncoding.EncodeToString(b), nil } const ( BaseTs = 1530687318000 //2018/7/4 14:55:18 SeqLen = 12 WorkerLen = 10 WorkerMask = 1< MaxWorkId || start < 0 || end > MaxWorkId || end < 0 || start > end { panic(errors.New("wrong para")) } idg.idStart = int64(start) idg.idEnd = int64(end) idg.idCur = int64(start) idg.lastTs = -1 idg.seq = 0 return idg, nil } func NewIdGenerator(start, end int64) (*UidGenerator, error) { idg := new(UidGenerator) if start > MaxWorkId || start < 0 || end > MaxWorkId || end < 0 || start > end { panic(errors.New("wrong para")) } idg.idStart = start idg.idEnd = end idg.idCur = start idg.lastTs = -1 idg.seq = 0 return idg, nil } func (idg *UidGenerator) getMs() int64 { return time.Now().UnixNano() / 1000000 } func (idg *UidGenerator) Next() (id int64, err error) { idg.lock.Lock() defer idg.lock.Unlock() now := idg.getMs() if now < idg.lastTs { //incase time schew time.Sleep(time.Duration(idg.lastTs-now) * time.Millisecond) now = idg.getMs() } if now == idg.lastTs { idg.seq = (idg.seq + 1) % SeqMask if idg.seq == 0 { if idg.idCur < idg.idEnd { idg.idCur = idg.idCur + 1 } else { cur := idg.lastTs * 1000000 for { now = time.Now().UnixNano() //wait next slot if now > cur { now = now / 1000000 break } } idg.seq = 0 idg.idCur = idg.idStart } } } else { idg.seq = 0 idg.idCur = idg.idStart } idg.lastTs = now id = (now-BaseTs)<