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/

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go