snowflake.go
package snowflake
import (
"fmt"
"time"
"errors"
)
/*
组成:0(1 bit) | timestamp in milli second (41 bit) | machine id (10 bit) | index (12 bit)
每毫秒最多生成4096个id,集群机器最多1024台
*/
type Snowflake struct {
lastTimestamp int64
index int16
machId int16
}
func (s *Snowflake)Init(id int16) error {
if id > 0xff {
return errors.New("illegal machine id")
}
s.machId = id
s.lastTimestamp = time.Now().UnixNano()/1e6
s.index = 0
return nil
}
func (s *Snowflake)GetId() (int64, error) {
curTimestamp := time.Now().UnixNano()/1e6
if (curTimestamp == s.lastTimestamp) {
s.index++
if(s.index>0xfff) {
s.index = 0xfff
return -1,errors.New("out of range")
}
} else {
//fmt.Printf("id/ms:%d -- %d\n", s.lastTimestamp, s.index)
s.index = 0
s.lastTimestamp = curTimestamp
}
return int64((0x1ffffffffff & s.lastTimestamp) << 22) + int64(0xff << 10) + int64(0xfff & s.index),nil
}
var UUID Snowflake
单元测试
snowflake_test.go
package snowflake
import (
"github.com/deckarep/golang-set"
"testing"
)
// 生成1亿个ID看有没有重复
func TestSnowFlake( t *testing.T ) {
UUID.Init(1024)
s := mapset.NewSet()
for i:=0;i<1e9;i++ {
id,err := UUID.GetId()
if err!= nil {
t.FailNow()
}
if(s.Add(id) == false) {
t.FailNow()
}
}
}
把代码都放到同一个文件夹下,运行
go test -v snowflake_test.go snowflake.go
有疑问加站长微信联系(非本文作者)