labix.org/v2/mgo/bson 包虽然是MongoDB的golang实现,其中产生唯一ID的算法是独立的,不依赖MongoDB, 提炼这部分的代码如下:

 

package main

import (
    "crypto/md5"
    "crypto/rand"
    "encoding/binary"
    "encoding/hex"
    "fmt"
    "io"
    "os"
    "sync/atomic"
    "time"
)

// objectIdCounter is atomically incremented when generating a new ObjectId
// using NewObjectId() function. It's used as a counter part of an id.
var objectIdCounter uint32 = 0

// machineId stores machine id generated once and used in subsequent calls
// to NewObjectId function.
var machineId = readMachineId()

// ObjectId is a unique ID identifying a BSON value. It must be exactly 12 bytes
// long. MongoDB objects by default have such a property set in their "_id"
// property.
//
// http://www.mongodb.org/display/DOCS/Object+IDs
type ObjectId string

func main() {
    objID := NewObjectId()
    fmt.Println(objID)
    fmt.Println(objID.Hex())
}

// 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 readMachineId() []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))
    fmt.Println("readMachineId:" + string(id))
    return id
}

// NewObjectId returns a new unique ObjectId.
// 4byte 时间,
// 3byte 机器ID
// 2byte pid
// 3byte 自增ID
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.AddUint32(&objectIdCounter, 1)
    b[9] = byte(i >> 16)
    b[10] = byte(i >> 8)
    b[11] = byte(i)
    return ObjectId(b[:])
}

// Hex returns a hex representation of the ObjectId.
// 返回16进制对应的字符串
func (id ObjectId) Hex() string {
    return hex.EncodeToString([]byte(id))
}

执行结果截图:

参考资料:

mgo说明文档
http://godoc.org/labix.org/v2/mgo/bson

Golang binary包——byte数组如何转int?
http://blog.cyeam.com/hash/2014/07/29/go_bytearraytoint/

golang产生guid的更多相关文章

  1. GOLANG 加密,解密,GUID 小方法

    golang的 MD5加密.BASE64解密  guid 的代码: /** * 用于加密,解密,(包含MD5加密和base64加密/解密)以及GUID的生成 * 时间: * zhifieya */ p ...

  2. Dapr Pub/Sub 集成 RabbitMQ 、Golang、Java、DotNet Core

    前置条件: <Dapr运用> <Dapr 运用之 Java gRPC 调用篇> <Dapr 运用之集成 Asp.Net Core Grpc 调用篇> 搭建 Rabb ...

  3. golang xml解析

    第二章里还提到了xml的解析部分.之前有想整理下encoding包下常用的几个文件格式的处理.这次刚好整理下xml的部分.先上例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 ...

  4. golang语法笔记

    开始微服务,那就先温习下golang语法吧; golang变量类型 1. 整形 Go %b    表示为二进制 %c    该值对应的unicode码值 %d    表示为十进制 %o    表示为八 ...

  5. Golang中如何正确的使用sarama包操作Kafka?

    Golang中如何正确的使用sarama包操作Kafka? 一.背景 在一些业务系统中,模块之间通过引入Kafka解藕,拿IM举例(图来源): 用户A给B发送消息,msg_gateway收到消息后,投 ...

  6. Golang, 以17个简短代码片段,切底弄懂 channel 基础

    (原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...

  7. 说说Golang的使用心得

    13年上半年接触了Golang,对Golang十分喜爱.现在是2015年,离春节还有几天,从开始学习到现在的一年半时间里,前前后后也用Golang写了些代码,其中包括业余时间的,也有产品项目中的.一直 ...

  8. TODO:Golang指针使用注意事项

    TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...

  9. UniqueIdentifier 数据类型 和 GUID 生成函数

    UniqueIdentifier 数据类型用于存储GUID的值,占用16Byte. SQL Server将UniqueIdentifier存储为16字节的二进制数值,Binary(16),按照特定的格 ...

随机推荐

  1. 就这么简单!构建强大的WebShell防护体系

    接触web安全中,例如上传一句话WebShell实现上传文件的功能,再通过上传的多功能WebShell,执行病毒文件最终创建远程连接账号,达到入侵目标服务器的效果.我们可以看到,webshell在整个 ...

  2. Bootstrap Modal 关闭时右侧滚动条消失,页面左移的解决方法

    问题描述:页面在打开Modal之前右侧有滚动条,Modal关闭之后,body中的class="modal-open"和style="padding-right: 17px ...

  3. php解析word,获得文档中的图片

    背景 前段时间在写一个功能:用原生php将获得word中的内容并导入到网站系统中.因为文档中存在公式,图片,表格等,因此写的比较麻烦. 思路 大体思路是先将word中格式为doc的文档转化为docx, ...

  4. 47.ActiveMQ集群

    (声明:本文非EamonSec原创) 使用ZooKeeper实现的Master-Slave实现方式,是对ActiveMQ进行高可用的一种有效的解决方案,高可用的原理:使用ZooKeeper(集群)注册 ...

  5. springcloud应用思考

    1 springcloud注册中心eureka和zookeeper注册中心的区别: eureka注册中心,在服务选主的时候服务还是可以用的,zookeeper注册中心在选举的时候整个服务瘫痪了,是不可 ...

  6. Hexo博客系列(三)-将Hexo v3.x个人博客发布到GitLab Pages

    [原文链接]:https://www.tecchen.xyz/blog-hexo-env-03.html 我的个人博客:https://www.tecchen.xyz,博文同步发布到博客园. 由于精力 ...

  7. 题解 p2017 [USACO09DEC]晕牛Dizzy Cows

    前言:P大终于又更新了 正文 转送门 由于当时我这个ZZ不知怎么了,这份题解排版可能有些尴尬,建议大家读完题后,看我主程序前的代码的注释,然后看最下面的图片,然后看第一张图片,对不起,望多谅解 以样例 ...

  8. RocketMQ之NameServer学习笔记

    org.apache.rocketmq.namesrv.NamesrvController NameserController,NameServer的核心控制类. 1.1 NamesrvConfig ...

  9. Java集合类中的Iterator和ListIterator的区别

    注意:内容来自网络他人文章! 最近看到集合类,知道凡是实现了Collection接口的集合类,都有一个Iterator方法,用于返回一个实现了Iterator接口的对象,用于遍历集合:(Iterato ...

  10. C# 数组基础

    一.数组的基础知识 1.数组有什么用? 如果需要同一个类型的多个对象,就可以使用数组.数组是一种数组结构,它可以包含同一个类型的多个元素. 2.数组的初始化方式 第一种:先声明后赋值 ]; array ...