golang产生guid

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/

时间: 2024-11-14 12:56:55

golang产生guid的相关文章

GOLANG 加密,解密,GUID 小方法

golang的 MD5加密.BASE64解密  guid 的代码: /** * 用于加密,解密,(包含MD5加密和base64加密/解密)以及GUID的生成 * 时间: * zhifieya */ package safe import ( "crypto/md5" "crypto/rand" "crypto/sha1" "encoding/base64" "encoding/hex" "io&q

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

前置条件: <Dapr运用> <Dapr 运用之 Java gRPC 调用篇> <Dapr 运用之集成 Asp.Net Core Grpc 调用篇> 搭建 RabbitMQ Docker 搭建 RabbitMQ 服务 docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management 创建 rabbiqmq.yaml apiVers

golang []byte转string

golang中,字符切片[]byte转换成string最简单的方式是 package main import ( "fmt" _ "unsafe" ) func main() { bytes := []byte("I am byte array !") str := string(bytes) bytes[0] = 'i'//注意这一行,bytes在这里修改了数据,但是str打印出来的依然没变化, fmt.Println(str) } 打印信息:

golang实现Ringbuf

Ring buffer算法优点:高内存使用率,在缓冲buffer内存模型中,不太容易发生内存越界.悬空指针等 bug ,出了问题也容易在内存级别分析调试.做出来的系统容易保持健壮. package main import ( "bytes" "fmt" ) type Ringbuf struct { buf         []byte start, size int } func New(size int) *Ringbuf { return &Ringb

Golang Hash MD4

//Go标准包中只有MD5的实现 //还好,github上有MD4实现. package main import (     "golang.org/x/crypto/md4"     "encoding/hex"     "fmt" ) func get_md4(buf []byte) ([] byte) { ctx := md4.New() ctx.Write(buf) return ctx.Sum(nil) } func main() {

Java程序员的Golang入门指南(上)

Java程序员的Golang入门指南 1.序言 Golang作为一门出身名门望族的编程语言新星,像豆瓣的Redis平台Codis.类Evernote的云笔记leanote等. 1.1 为什么要学习 如果有人说X语言比Y语言好,两方的支持者经常会激烈地争吵.如果你是某种语言老手,你就是那门语言的"传道者",下意识地会保护它.无论承认与否,你都已被困在一个隧道里,你看到的完全是局限的.<肖申克的救赎>对此有很好的注脚: [Red] These walls are funny.

golang学习笔记:golang 语法篇(二)

在语法篇(一)中学习了go中基本的数据类型.变量.常量等组成语言的基本要素,在这一节中将会学习如何将这些元素组织起来,最终写成可以执行的代码. 在这一部分包括: go中的流程控制语句: go中函数的用法: go特殊的错误处理方式: Golang中的流程控制语句 在具体编程的时候免不了需要使用一些特殊的语句实现某些功能,比如使用循环语句来进行迭代,使用选择语句控制程序的执行方式等.这些语句在任何一门程序设计语言 中都会有支持,golang中除了支持常用的循环,条件选择语句以外,还支持跳转语句,下面

GuId为空的判断

随着学习的深入和项目开发的需求的变化,接触到了GuId.它是业界大亨微软使用的,通过一种复杂的算法生成,该算法保证所有的COM对象都有着唯一的ID,而不会出现名字冲突.保证了我们在大数据量的开发中标识唯一. Guid适用于多平台.多领域,给我们的开发带来的诸多的方便,同时也避免了开发中很多的问题,自己也是感同身受!但在对Guid为空的判断时却遇到了问题,网上找了很多的资料有各种各样的解决方案,但是并不是很适用于自己的情况,下面就将自己的办法分享给大家,希望可以惠及到更多的人! 由于Guid返回的

Golang关键字—— if/else

Golang中,if/else 关键字用于条件判断,如果满足条件就做某事,否则做另一件事: if age >= 18 { fmt.Println("成年人") } else { fmt.Println("未成年") } 多重判断: if score >= 90 { fmt.Println("优秀") } else if score >= 70 { fmt.Println("良好") } else if sco