objectid.go源码阅读
/*
具体实现理论参见 mongodb官方 objectid生成策略
http://docs.mongodb.org/manual/reference/object-id/
ObjectId 是一个由12字节组成的bson数据,按照字节顺序,一次代表:
ObjectId is a 12-byte BSON type, constructed using:
4个字节代表1970年元月一日到现在毫秒数 UNIX时间戳
a 4-byte value representing the seconds since the Unix epoch,
3个字节代表机器的唯一标识符 表示运行的机器
a 3-byte machine identifier,
2个字节代表进程的id 表示生成此_id的进程
a 2-byte process id, and
3个字节代表计数器,开始带着一个随机数 由一个随机数开始的计数器生成的值
a 3-byte counter, starting with a random value.
*/
package objectid
import (
"crypto/md5"
"encoding/hex"
"fmt"
"math/rand"
"os"
"sync/atomic"
"time"
)
var staticMachine = getMachineHash() //获取机器的id
var staticIncrement = getRandomNumber()//获取随机数
var staticPid = int32(os.Getpid())//获取进程id
//
type ObjectId struct {
timestamp int64
machine int32
pid int32
increment int32
}
//
func New() *ObjectId {
timestamp := time.Now().Unix()
return &ObjectId{timestamp, staticMachine, staticPid, atomic.AddInt32(&staticIncrement, 1) & 0xffffff}
}
//
func Parse(input string) *ObjectId {
if len(input) == 0 {
panic("The input is empty.")
}
if value, ok := tryParse(input); ok {
return value
}
panic(fmt.Sprintf("%s is not a valid 24 digit hex string.", input))
}
//
func (this *ObjectId) Timestamp() int64 {
return this.timestamp
}
//
func (this *ObjectId) Machine() int32 {
return this.machine
}
//
func (this *ObjectId) Pid() int32 {
return this.pid
}
//
func (this *ObjectId) Increment() int32 {
return this.increment & 0xffffff
}
//
func (this *ObjectId) CreationTime() time.Time {
return time.Unix(this.timestamp, 0)
}
//
func (this *ObjectId) Equal(other *ObjectId) bool {
return this.timestamp == other.timestamp &&
this.machine == other.machine &&
this.pid == other.pid &&
this.increment == other.increment
}
//
func (this *ObjectId) String() string {
array := []byte{
byte(this.timestamp >> 0x18),
byte(this.timestamp >> 0x10),
byte(this.timestamp >> 8),
byte(this.timestamp),
byte(this.machine >> 0x10),
byte(this.machine >> 8),
byte(this.machine),
byte(this.pid >> 8),
byte(this.pid),
byte(this.increment >> 0x10),
byte(this.increment >> 8),
byte(this.increment),
}
return hex.EncodeToString(array)
}
//获取机器唯一标识符
func getMachineHash() int32 {
machineName, err := os.Hostname()
if err != nil {
panic(err)
}
buf := md5.Sum([]byte(machineName))
return (int32(buf[0])<<0x10 + int32(buf[1])<<8) + int32(buf[2])
}
//获取随机数开始的计数器生成的值
func getRandomNumber() int32 {
rand.Seed(time.Now().UnixNano())
return rand.Int31()
}
//从字符串objectid 解析成为ObjectId
func tryParse(input string) (*ObjectId, bool) {
if len(input) != 0x18 {
return nil, false
}
array, err := hex.DecodeString(input) //十六进制的字符串 转化为字节切片
if err != nil {
return nil, false
}
return &ObjectId{
timestamp: int64(array[0])<<0x18 + int64(array[1])<<0x10 + int64(array[2])<<8 + int64(array[3]),
//转化为十进制的int64 新纪元时间 毫秒
machine: int32(array[4])<<0x10 + int32(array[5])<<8 + int32(array[6]),
//转化为十进制的int32数据 机器唯一标识符
pid: int32(array[7])<<8 + int32(array[8]),
// 当前进程id
increment: int32(array[9])<<0x10 + (int32(array[10]) << 8) + int32(array[11]),
// 随机数开始的计数器生成的值
}, true
}
objectid.go源码阅读的更多相关文章
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】FMDB源码阅读(二)
[原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...
- 【原】FMDB源码阅读(一)
[原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...
- 【原】AFNetworking源码阅读(六)
[原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...
- 【原】AFNetworking源码阅读(五)
[原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...
- 【原】AFNetworking源码阅读(四)
[原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...
- 【原】AFNetworking源码阅读(三)
[原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...
- 【原】AFNetworking源码阅读(二)
[原]AFNetworking源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中我们在iOS Example代码中提到了AFHTTPSessionMa ...
- 【原】AFNetworking源码阅读(一)
[原]AFNetworking源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 AFNetworking版本:3.0.4 由于我平常并没有经常使用AFNetw ...
随机推荐
- obj-c编程06:反射与元编程初步
我们知道对于现如今的动态语言比如ruby而言,反射和元编程以及支持的非常灵活了,你完全可以跳过常规的手段,而利用反射来查询或调用对象的私有方法.而obj-c对反射的支持略显小繁琐,而且在开了ARC后同 ...
- OpenLayers3的轨迹回放
OpenLayers3实现轨迹回放需要动画操作,官网上的例子用的是postcompose,但是还可以使用javascript中setInterval和setTime. 我的例子是按官网上来的http: ...
- JVM学习--(八)java堆分析
上一节介绍了针对JVM的监控工具,包括JPS可以查看当前所有的java进程,jstack查看线程栈可以帮助你分析是否有死锁等情况,jmap可以导出java堆文件在MAT工具上进行分析等等.这些工具都非 ...
- objc/runtime.h 查看私有api
objc/runtime.h 相关 Objecitve-C的重要特性是Runtime(运行时),在Interacting with the Runtime(交互运行)中,运行时函数部分,苹果给出了/u ...
- 2.3MySQL 自带工具使用介绍
1.mysql 首先看看“-e, --execute=name”参数,这个参数是告诉mysql,我只要执行“-e”后面的某个命令,而不是要通过mysql 连接登录到MySQL Server 上面.此参 ...
- python结巴(jieba)分词
python结巴(jieba)分词 一.特点 1.支持三种分词模式: (1)精确模式:试图将句子最精确的切开,适合文本分析. (2)全模式:把句子中所有可以成词的词语都扫描出来,速度非常快,但是不能解 ...
- 摘抄详细的VUE生命周期
Vue所有的生命周期钩子自动绑定在this上下文到实例中,因此你可以访问数据,对属性和方法进行运算.这意味着你不能使用箭头函数来定义一个生命周期方法.这是因为箭头函数绑定了父上下文,因此this与你 ...
- Spring Security简明实践及相关国际化处理
别人的都是最佳实践,因为我目前的设置没有按照参考文档推荐,还是采用DelegatingFilterProxy,所以我只能说简明实践.先贴我的applicationContext-security.xm ...
- ERR_NAME_NOT_RESOLVED错误的解决
参考:http://zhidao.baidu.com/link?url=-Beq80OXoSKef_9SmGXkQHvq2AkSE0aGfac02ykorglQF6JTP7F1XNtVxFn9EMfn ...
- win10更新失败——适用于Windows 10 Version 1709 的03累积更新,适合基于x64系统(KB4088776)更新失败
相信最近很多人被windows的更新折磨坏了,下面来介绍一下解决办法,有用的话请点赞! 首先将C盘中的这个文件夹删除:"C:\Windows\System32\Tasks\Microsoft ...