Skip to content

Instantly share code, notes, and snippets.

@easyfmxu
Forked from asyncins/snowflake.go
Created July 4, 2020 22:41
Show Gist options
  • Save easyfmxu/5f5deccf1e5613ced10b9192abc911d4 to your computer and use it in GitHub Desktop.
Save easyfmxu/5f5deccf1e5613ced10b9192abc911d4 to your computer and use it in GitHub Desktop.

Revisions

  1. @asyncins asyncins created this gist Jul 3, 2020.
    75 changes: 75 additions & 0 deletions snowflake.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,75 @@
    package main

    import (
    "errors"
    "fmt"
    "sync"
    "time"
    )

    const (
    twepoch = int64(1483228800000) //开始时间截 (2017-01-01)
    workeridBits = uint(10) //机器id所占的位数
    sequenceBits = uint(12) //序列所占的位数
    workeridMax = int64(-1 ^ (-1 << workeridBits)) //支持的最大机器id数量
    sequenceMask = int64(-1 ^ (-1 << sequenceBits)) //
    workeridShift = sequenceBits //机器id左移位数
    timestampShift = sequenceBits + workeridBits //时间戳左移位数
    )

    // A Snowflake struct holds the basic information needed for a snowflake generator worker
    type Snowflake struct {
    sync.Mutex
    timestamp int64
    workerid int64
    sequence int64
    }

    // NewNode returns a new snowflake worker that can be used to generate snowflake IDs
    func NewSnowflake(workerid int64) (*Snowflake, error) {

    if workerid < 0 || workerid > workeridMax {
    return nil, errors.New("workerid must be between 0 and 1023")
    }

    return &Snowflake{
    timestamp: 0,
    workerid: workerid,
    sequence: 0,
    }, nil
    }

    // Generate creates and returns a unique snowflake ID
    func (s *Snowflake) Generate() int64 {

    s.Lock()

    now := time.Now().UnixNano() / 1000000

    if s.timestamp == now {
    s.sequence = (s.sequence + 1) & sequenceMask

    if s.sequence == 0 {
    for now <= s.timestamp {
    now = time.Now().UnixNano() / 1000000
    }
    }
    } else {
    s.sequence = 0
    }

    s.timestamp = now

    r := int64((now-twepoch)<<timestampShift | (s.workerid << workeridShift) | (s.sequence))

    s.Unlock()
    return r
    }

    func main() {
    snow := Snowflake{}
    for i := 0; i < 3; i++ {
    id := snow.Generate()
    fmt.Println(id)
    }
    }