package strutilimport (// TODO use v2 on 1.22+)// global id://// https://github.com/rs/xid// https://github.com/satori/go.uuidvar (DefMinInt = 1000DefMaxInt = 9999)// MicroTimeID generate.// - return like: 16074145697981929446(len: 20)//// Conv Base://// mtId := MicroTimeID() // eg: 16935349145643425047 len: 20// b16id := Base10Conv(mtId, 16) // eg: eb067252154a9d17 len: 16// b32id := Base10Conv(mtId, 32) // eg: em1jia8akl78n len: 13// b36id := Base10Conv(mtId, 36) // eg: 3ko088phiuoev len: 13// b62id := Base10Conv(mtId, 62) // eg: kb24SKgsQ9V len: 11func () string { returnMTimeBaseID(10) }// MicroTimeHexID micro time HEX ID generate.//// return like: 643d4cec7db9e(len: 13)func () string { returnMTimeHexID() }// MTimeHexID micro time HEX ID generate.//// return like: 643d4cec7db9e(len: 13)func () string { returnMTimeBaseID(16) }// MTimeBase36 micro time BASE36 id generate.func () string { returnMTimeBaseID(36) }// MTimeBaseID micro time BASE id generate. toBase: 2-36//// Examples:// - toBase=16: 643d4cec7db9e(len: 13)// - toBase=36: hd312z9ka2(len: 10)func ( int) string {// eg: 1763431181849557 := time.Now().UnixMicro()// rand 1000 - 9999 // ri := mathutil.RandomInt(DefMinInt, DefMaxInt) := 1000 + rand.Int63n(8999)if > 36 {returnBaseConvInt(uint64()+uint64(), ) }returnstrconv.FormatInt(+, )}// DatetimeNo generate. can use for order-no.//// - No prefix, return like: 2023041410484904074285478388(len: 28)// - With prefix, return like: prefix2023041410484904074285478388(len: 28 + len(prefix))func ( string) string { returnDateSN() }// DateSN generate date serial number. PREFIX + yyyyMMddHHmmss + ext(微秒+随机数)func ( string) string { := time.Now() := len() := make([]byte, 0, 28+)if > 0 { = append(, ...) }// micro datetime = .AppendFormat(, "20060102150405.000000") [14+] = '0'// host , := os.Hostname()if != nil { = "default" } := crc32.ChecksumIEEE([]byte()) // eg: 4006367001 = strconv.AppendUint(, uint64(%99), 10)// rand 1000 - 9999 // rs := rand.New(rand.NewSource(nt.UnixNano())) = strconv.AppendInt(, 1000+rand.Int63n(8999), 10)returnstring()}// DateSNOpt 基于时间生成唯一编号typeDateSNOptstruct { Layout string// time layout// RandMax int // rand max DateLen int// 时间格式长度,后面部分将会进行进制转换 默认 8(yyyyMMdd) ConvBase int// DateLen 之后的转换 base 2-64. default 36// EnableSeq bool // 需要高并发生成时可以启用自增序号。默认不启用 SeqMaxVal int// 自增序号最大值,之后后自动重置 globalSeq int64// 自增,确保同一时刻生成的编号不重复. EnableSeq=true 时启用}// default setting: {时间年到秒14位}var defOpt = NewDateSNOpt()// ConfigSNOpt config default date sn optionfunc ( func( *DateSNOpt)) { (defOpt)}// NewDateSNOpt create a new DateSNOpt instance.func () *DateSNOpt {return &DateSNOpt{Layout: "20060102150405.000000",// RandMax: 8999,DateLen: 8,ConvBase: 36,// EnableSeq: true,SeqMaxVal: 8999, }}// prepare for generatefunc ( *DateSNOpt) () {if .DateLen <= 0 { .DateLen = 8// default 8 for yyyyMMdd }if .ConvBase <= 0 { .ConvBase = 36 }if .Layout == "" { .Layout = "20060102150405.000000" }// get sequence max value (default 9999)if .SeqMaxVal <= 0 { .SeqMaxVal = 8999 }}func ( *DateSNOpt) () int64 {// use atomic sequence for guaranteed uniqueness (even without EnableSeq) // this ensures no collisions in tight loops := atomic.AddInt64(&.globalSeq, 1)// auto reset when seq exceeds SeqMaxVal (thread-safe using CAS)if > int64(.SeqMaxVal) {// try to reset to 1, other goroutines may have already done itatomic.CompareAndSwapInt64(&.globalSeq, , 1) = % int64(.SeqMaxVal)if == 0 { = 1 } }return1000 + }// GenSN generate date serial number.func ( *DateSNOpt) ( string) string { := len() := make([]byte, 0, 22+)if > 0 { = append(, ...) } .prepare()// get time and format := time.Now() = .AppendFormat(, .Layout)// remove the dot separator if exists := -1for := ; < len(); ++ {if [] == '.' { = break } }if > 0 { = append([:], [+1:]...) }// determine date length (default 8 for yyyyMMdd) := .DateLen + // high concurrency mode: sequence is the main differentiator := strconv.AppendInt([:], .getSeqValue(), 10)if [0] == '0' { [0] = '1' } := SafeUint(string())// convert extension to target base = append([:], BaseConvInt(, .ConvBase)...)returnstring()}// 确保同一时刻生成的编号不重复 max: 89999var globalSeqSnV2 int64 = 0func getSeqValue() int64 {// use atomic sequence for guaranteed uniqueness (even without EnableSeq) // this ensures no collisions in tight loops := atomic.AddInt64(&globalSeqSnV2, 1)// auto reset when seq exceeds SeqMaxVal (thread-safe using CAS)if > 89999 {// try to reset to 1, other goroutines may have already done itatomic.CompareAndSwapInt64(&globalSeqSnV2, , 1) = % 89999if == 0 { = 1 } }return}// DateSNv2 generate date serial number.// - 2 < extBase <= 36// - return: PREFIX + yyyyMMddHHmmss + extBase(6bit micro + 5bit random number)//// Example:// - prefix=P, extBase=16, return: P2023091414361354b4490(len=22)// - prefix=P, extBase=36, return: P202309141436131gw3jg(len=21)func ( string, ...int) string { := len() := make([]byte, 0, 22+)if > 0 { = append(, ...) }// micro datetime := time.Now() = .AppendFormat(, "20060102150405.000000")// 6bit micro + 5bit rand 10000 - 99999 // ext := strconv.AppendInt(bs[16+pl:], 10000+rand.Int63n(89999), 10) := strconv.AppendInt([16+:], 10000+getSeqValue(), 10)// prefix + yyyyMMddHHmmss + ext(convert to base) := basefn.FirstOr(, 36) = append([:14+], strconv.FormatInt(SafeInt64(string()), )...)returnstring()}var (// key is dateLen + extBase dsoMap = make(map[string]*DateSNOpt) dsoMutex sync.RWMutex)// DateSNv3 generate date serial number.// - 2 < extBase <= 64// - return: PREFIX + DATETIME(yyyyMMddHHmmss).dateLen + extBase(DATETIME.after+6bit micro + 5bit random number)// - dateLen: 为 DATETIME(yyyyMMddHHmmss) 保留的长度,默认为 8(yyyyMMdd) 后面的给 extBase 使用//// Example:// - prefix=P, dateLen=8, extBase=16, return: P202511139vs99gbifnj len: 20// - prefix=P, dateLen=6, extBase=36, return: P2025119yn52qhefati len: 19// - prefix=P, dateLen=6, extBase=48, return: P202511k9ksgD1fe6x len: 18// - prefix=P, dateLen=4, extBase=62, return: P2025aZl8N0y58M7 len: 16func ( string, int, ...int) string { := basefn.FirstOr(, 36) := fmt.Sprintf("%d%d", , )dsoMutex.RLock() , := dsoMap[]dsoMutex.RUnlock()if ! {dsoMutex.Lock()// double check,防止在加锁期间其他 goroutine 已经创建if , = dsoMap[]; ! { = NewDateSNOpt()// dso.EnableSeq = true .DateLen = .ConvBase = dsoMap[] = }dsoMutex.Unlock() }return .GenSN()}
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.