GoLang雪花算法和反推
2023-09-27 14:25:41 时间
工具代码
package log
import (
"crypto/md5"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"os"
"sync/atomic"
"time"
)
// LogId is a unique ID identifying a log record. It must be exactly 12 bytes
// long.
//
// Reference:http://www.mongodb.org/display/DOCS/Object+IDs
type ObjectId [12]byte
var (
// objectIdCounter is atomically incremented when generating a new ObjectId
// using NewObjectId() function. It's used as a counter part of an id.
objectIdCounter uint64 = 0
// machineId stores machine id generated once and used in subsequent calls
// to NewObjectId function.
machineId = initMachineId()
)
// readMachineId generates machine id and puts it into the machineId global
// variable. If this function fails to get the hostname, it will cause
// a runtime error.
func initMachineId() []byte {
var sum [3]byte
id := sum[:]
hostname, err1 := os.Hostname()
if err1 != nil {
_, err2 := io.ReadFull(rand.Reader, id)
if err2 != nil {
panic(fmt.Errorf("cannot get hostname: %v; %v", err1, err2))
}
return id
}
hw := md5.New()
hw.Write([]byte(hostname))
copy(id, hw.Sum(nil))
return id
}
func StrToObjectId(str string) ObjectId {
byteArr,err := hex.DecodeString(str)
if err != nil {
panic(err.Error())
}
var b[12]byte
i := 0
for {
if i == 12{
break
}
b[i] = byteArr[i]
i++
}
return b
}
// NewObjectId returns a new unique ObjectId.
func NewObjectId() ObjectId {
var b [12]byte
// Timestamp, 4 bytes, big endian
binary.BigEndian.PutUint32(b[:], uint32(time.Now().Unix()))
// Machine, first 3 bytes of md5(hostname)
b[4] = machineId[0]
b[5] = machineId[1]
b[6] = machineId[2]
// Pid, 2 bytes, specs don't specify endianness, but we use big endian.
pid := os.Getpid()
b[7] = byte(pid >> 8)
b[8] = byte(pid)
// Increment, 3 bytes, big endian
i := atomic.AddUint64(&objectIdCounter, 1)
b[9] = byte(i >> 16)
b[10] = byte(i >> 8)
b[11] = byte(i)
return b
}
// NewObjectIdWithTime returns a dummy ObjectId with the timestamp part filled
// with the provided number of seconds from epoch UTC, and all other parts
// filled with zeroes. It's not safe to insert a document with an id generated
// by this method, it is useful only for queries to find documents with ids
// generated before or after the specified timestamp.
func NewObjectIdWithTime(t time.Time) ObjectId {
var b [12]byte
binary.BigEndian.PutUint32(b[:4], uint32(t.Unix()))
return b
}
func NewObjectIdWithHexString(s string) (o ObjectId) {
d, err := hex.DecodeString(s)
if err != nil || len(d) != 12 {
panic(fmt.Sprintf("invalid input to ObjectIdHex: %q", s))
}
copy(o[:], d[:12])
return
}
// Hex returns a hex representation of the ObjectId.
func (id ObjectId) Hex() string {
return hex.EncodeToString(id[:])
}
// Time returns the timestamp part of the id.
// It's a runtime error to call this method with an invalid id.
func (id ObjectId) Time() time.Time {
// First 4 bytes of ObjectId is 32-bit big-endian seconds from epoch.
secs := int64(binary.BigEndian.Uint32(id[:4]))
return time.Unix(secs, 0)
}
// Machine returns the 3-byte machine id part of the id.
// It's a runtime error to call this method with an invalid id.
func (id ObjectId) Machine() []byte {
return id[4:7]
}
// Pid returns the process id part of the id.
// It's a runtime error to call this method with an invalid id.
func (id ObjectId) Pid() uint16 {
return binary.BigEndian.Uint16(id[7:9])
}
// Counter returns the incrementing value part of the id.
// It's a runtime error to call this method with an invalid id.
func (id ObjectId) Counter() int32 {
b := id[9:12]
// Counter is stored as big-endian 3-byte value
return int32(uint32(b[0])<<16 | uint32(b[1])<<8 | uint32(b[2]))
}
测试:
func main() {
id := log.NewObjectId().Hex()
fmt.Println(id)
logId := log.StrToObjectId(id)
fmt.Println(logId.Hex())
fmt.Println(logId.Time())
fmt.Println(logId.Machine())
fmt.Println(logId.Pid())
fmt.Println(logId.Counter())
}
结果:
whydeMacBook-Pro:go why$ go run test.go
5e394e99a7f8a34d810303d4
5e394e99a7f8a34d810303d4
2020-02-04 18:59:37 +0800 CST
[167 248 163]
19841
1
相关文章
- 算法基础:整数拆分问题(Golang实现)
- 【算法】【二叉树模块】求一个二叉树“子树“是否包含另一个二叉树的全部拓扑结构
- LeetCode 21-25 题 详解 Java版 ( 万字 图文详解 LeetCode 算法题21-25 =====>>> <建议收藏>)
- 递归算法
- Java实现内存分配算法 FF(首次适应算法) BF(最佳适应算法)
- LeetCode左程云算法课笔记(整理ing)
- 机器学习常见算法的性能比较
- 机器学习的9个基础概念和10种基本算法总结
- (转)滑动平均法、滑动平均模型算法(Moving average,MA)
- [算法课][贪心]W12自学2密码发生器
- [算法课]全面翻新计划!第八周全解
- baselines算法库common/tile_images.py模块分析
- 贪心算法
- 【算法/位运算】常见位运算总结+刷题路线(15题)
- **试题 算法训练 石子游戏**
- 【源代码】将一个整数的每位数分解并按逆序放入一个数组中(用递归算法)(C语言实现)
- 实例分解神经网络反向传播算法(转)