zoukankan      html  css  js  c++  java
  • 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
    }
  • 相关阅读:
    JSP三大指令是什么?
    jsp和servlet的区别、共同点、各自应用的范围
    1.说一说Servlet的生命周期?
    .查询姓“李”的老师的个数;
    jquery 主要内容有两大部分:
    jQuery的优势:
    JDBC的PreparedStatement是什么?
    execute,executeQuery,executeUpdate的区别是什么?
    String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的
    数据维护不求人,一招搞定增删改
  • 原文地址:https://www.cnblogs.com/zhangboyu/p/7461907.html
Copyright © 2011-2022 走看看