package otherutils import ( "bytes" "fmt" "math/rand" "strings" "sync/atomic" "time" ) const ( charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" maxBase = 62 defaultBase = 61 maxOrderNum = 65536 ) var orderIncrId uint32 // 订单自增ID,每次重启从头开始即可 // ConvertToBaseN converts a decimal number to a string representation in the specified base (2-62) func ConvertToBaseN(decimalNum int64, base int64) (string, error) { if base <= 0 || base > maxBase { return "", fmt.Errorf("base must be between 1 and %d", maxBase) } if decimalNum == 0 { return "0", nil } if decimalNum < 0 { return "", fmt.Errorf("negative numbers are not supported") } var buf bytes.Buffer for decimalNum > 0 { remainder := decimalNum % base decimalNum /= base buf.WriteByte(charset[remainder]) } // Reverse the result result := buf.Bytes() for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 { result[i], result[j] = result[j], result[i] } return string(result), nil } // ConvertToDecimal converts a string in the specified base (2-62) to decimal func ConvertToDecimal(str string, base int64) (int64, error) { if base <= 0 || base > maxBase { return 0, fmt.Errorf("base must be between 1 and %d", maxBase) } if str == "" { return 0, fmt.Errorf("empty string is not valid") } var result int64 for i, char := range str { index := strings.IndexRune(charset, char) if index == -1 || index >= int(base) { return 0, fmt.Errorf("invalid character '%c' for base %d", char, base) } // Use multiplication instead of math.Pow to avoid floating point precision issues power := len(str) - i - 1 multiplier := int64(1) for j := 0; j < power; j++ { multiplier *= base } result += int64(index) * multiplier } return result, nil } // formatDateTime returns a compact string representation of the current time func formatDateTime(t time.Time) int64 { y, m, d := t.Date() h, mi, s := t.Hour(), t.Minute(), t.Second() return int64(y)*1e10 + int64(m)*1e8 + int64(d)*1e6 + int64(h)*1e4 + int64(mi)*1e2 + int64(s) } // CreateOutTradeNo generates a unique trade number func CreateOutTradeNo(playerId int64, serverId int64, zoneId int) string { n := atomic.AddUint32(&orderIncrId, 1) % maxOrderNum num := formatDateTime(time.Now()) baseN, _ := ConvertToBaseN(num, defaultBase) serverIdStr, _ := ConvertToBaseN(serverId, defaultBase) playerIdStr, _ := ConvertToBaseN(playerId, defaultBase) orderStr, _ := ConvertToBaseN(int64(n), defaultBase) return fmt.Sprintf("%sZ%sZ%sZ%sZ%d", baseN, serverIdStr, playerIdStr, orderStr, zoneId) } func TestCreateOutTradeNo() { var ( playerId = 1 serverId = 102 zoneId = 1 ) for i := 0; i < 10000; i += 1 { playerId += 10000000 orderCode := CreateOutTradeNo(int64(playerId), int64(serverId), zoneId) fmt.Println(orderCode) } } // 随机不含重复字符的字符串 // l长度 超过20需修改逻辑 命中会降低 func RandString(l int) string { cl := len(charset) if l > cl || l <= 0 { return "" } bytes := make([]byte, l) selected := make(map[byte]bool) for i := 0; i < l; { b := rand.Intn(cl) char := charset[b] if !selected[char] { bytes[i] = char selected[char] = true i++ } } return string(bytes) }