From 814bdf7d293b16c07d0206fd6682fc7a9d725b3f Mon Sep 17 00:00:00 2001 From: guzeng Date: Mon, 4 Sep 2023 10:20:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=9B=AA=E8=8A=B1=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E5=AE=9E=E7=8E=B0=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- snowflake.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++ snowflake_test.go | 16 ++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 snowflake.go create mode 100644 snowflake_test.go diff --git a/snowflake.go b/snowflake.go new file mode 100644 index 0000000..eecb0ed --- /dev/null +++ b/snowflake.go @@ -0,0 +1,62 @@ +package helper + +import ( + "sync" + "time" +) + +// Snowflake 结构体 +type Snowflake struct { + mu sync.Mutex + startTime int64 // 起始时间戳,可以根据实际需求设置 + machineID int64 // 机器ID + sequenceNum int64 // 序列号 +} + +// NewSnowflake 创建一个Snowflake实例 +func NewSnowflake(machineID int64) *Snowflake { + return &Snowflake{ + startTime: getTimeStamp(), + machineID: machineID, + sequenceNum: 0, + } +} + +// Generate 生成一个唯一ID +func (s *Snowflake) Generate() int64 { + s.mu.Lock() + defer s.mu.Unlock() + + currentTime := getTimeStamp() + + // 如果当前时间小于上一次生成ID的时间,说明时钟回拨,需要等待 + if currentTime < s.startTime { + time.Sleep(time.Duration(s.startTime - currentTime)) + currentTime = getTimeStamp() + } + + // 如果是同一毫秒内生成的ID,需要增加序列号 + if currentTime == s.startTime { + s.sequenceNum++ + } else { + s.sequenceNum = 0 + s.startTime = currentTime + } + + // 如果序列号超过了12位的最大值,等待下一毫秒再生成ID + if s.sequenceNum >= 1<<12 { + time.Sleep(time.Millisecond) + s.startTime = getTimeStamp() + s.sequenceNum = 0 + } + + // 生成ID + id := (currentTime-s.startTime)<<22 | (s.machineID << 12) | s.sequenceNum + + return id +} + +// 获取当前时间戳(毫秒级) +func getTimeStamp() int64 { + return time.Now().UnixNano() / int64(time.Millisecond) +} diff --git a/snowflake_test.go b/snowflake_test.go new file mode 100644 index 0000000..4e3375e --- /dev/null +++ b/snowflake_test.go @@ -0,0 +1,16 @@ +package helper + +import ( + "testing" +) + +func Test_snowflake(t *testing.T) { + + // 创建一个Snowflake实例 + snowflake := NewSnowflake(169379266710) + // 生成10个唯一ID并输出 + for i := 0; i < 10; i++ { + id := snowflake.Generate() + t.Log(id) + } +}