GoLang雪花算法和反推
工具代码
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雪花算法和反推”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!
您可能感兴趣的文章:
想系统学习GO语言(Golang
如何使用HTML5 canvas实现雪花飘落
GoLang雪花算法和反推
Illustrator绘制有型有色的抽象派玫瑰花教程分享
用canvas实现简单的下雪效果(附代码)
Golang 中 RSA 算法的使用
golang基础教程
拓展学习-golang的基础语法和常用开发工具
利用SurfaceView实现下雨与下雪动画的效果
用Golang写一个搜索引擎(0x0B)--- 第一部分结束