forked from free-lancers/electricity_bill_calc_service
合并分支
This commit is contained in:
84
tools/serial/algorithm.go
Normal file
84
tools/serial/algorithm.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package serial
|
||||
|
||||
import (
|
||||
"electricity_bill_calc/config"
|
||||
"electricity_bill_calc/logger"
|
||||
"electricity_bill_calc/types"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
log = logger.Named("Algorithm", "Unique Serial")
|
||||
SerialRequestChan = make(chan int64, 500)
|
||||
StringSerialRequestChan = make(chan int64, 500)
|
||||
SerialResponseChan = make(chan int64, 500)
|
||||
StringSerialResponseChan = make(chan string, 500)
|
||||
)
|
||||
|
||||
func init() {
|
||||
go func() {
|
||||
var (
|
||||
lastTimestamp int64 = 0
|
||||
lastSerial int64 = 0
|
||||
)
|
||||
log.Info("唯一序列号生成服务已经启动。")
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-SerialRequestChan:
|
||||
log.Info("收到生成数字型唯一序列号的请求。")
|
||||
timestamp := generateTimestamp(lastTimestamp)
|
||||
if timestamp != lastTimestamp {
|
||||
lastSerial = 0
|
||||
}
|
||||
lastSerial = lastSerial + 1
|
||||
uniqueId := generateSerial(timestamp, lastSerial)
|
||||
SerialResponseChan <- uniqueId
|
||||
lastTimestamp = timestamp
|
||||
case <-StringSerialRequestChan:
|
||||
log.Info("收到生成字符串型唯一序列号的请求。")
|
||||
timestamp := generateTimestamp(lastTimestamp)
|
||||
if timestamp != lastTimestamp {
|
||||
lastSerial = 0
|
||||
}
|
||||
lastSerial = lastSerial + 1
|
||||
uniqueId := generateStringSerial(timestamp, lastSerial)
|
||||
StringSerialResponseChan <- uniqueId
|
||||
lastTimestamp = timestamp
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 生成一个能够对抗服务器时间回拨的时间戳
|
||||
func generateTimestamp(base int64) int64 {
|
||||
for {
|
||||
timestamp := types.Timestamp()
|
||||
if timestamp >= base {
|
||||
return timestamp
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成一个唯一的数字型序列号
|
||||
func generateSerial(timestamp, serial int64) int64 {
|
||||
return (timestamp << 20) | ((config.ServiceSettings.HostSerial & 0xffff) << 16) | (serial & 0xffff_ffff)
|
||||
}
|
||||
|
||||
// 生成一个唯一的字符串型序列号
|
||||
func generateStringSerial(timestamp, serial int64) string {
|
||||
return fmt.Sprintf("%017d", generateSerial(timestamp, serial))
|
||||
}
|
||||
|
||||
// 生成一个带前缀字符串的唯一字符串型序列号
|
||||
func Prefix(prefix string, serial interface{}) string {
|
||||
switch serial := serial.(type) {
|
||||
case int64:
|
||||
return fmt.Sprintf("%s%017d", prefix, serial)
|
||||
case string:
|
||||
return fmt.Sprintf("%s%s", prefix, serial)
|
||||
}
|
||||
return ""
|
||||
}
|
@@ -2,10 +2,12 @@ package tools
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mozillazg/go-pinyin"
|
||||
"github.com/samber/lo"
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
func ContainsInsensitive(element string, slice []string) bool {
|
||||
@@ -51,3 +53,94 @@ func PartitionSlice[T any](slice []T, chunkSize int) [][]T {
|
||||
}
|
||||
return divided
|
||||
}
|
||||
|
||||
// 判断指定指针是否为空,如果为空,则返回指定默认值(指针形式)
|
||||
func DefaultTo[T any](originValue *T, defaultValue T) T {
|
||||
if originValue == nil {
|
||||
return defaultValue
|
||||
}
|
||||
return *originValue
|
||||
}
|
||||
|
||||
// 判断指定的指针是否为空,如果为空,则返回指定的默认字符串,或者返回指针所指内容的字符串形式。
|
||||
func DefaultStrTo[T any](format string, originValue *T, defaultStr string) string {
|
||||
if originValue == nil {
|
||||
return defaultStr
|
||||
}
|
||||
return fmt.Sprintf(format, originValue)
|
||||
}
|
||||
|
||||
// 判断指定字符串指针是否为`nil`或者字符串长度为空,如果是则返回给定的默认字符串,否则返回指针所指内容的字符串形式。
|
||||
func DefaultOrEmptyStr(originValue *string, defaultStr string) string {
|
||||
if originValue == nil || len(*originValue) == 0 {
|
||||
return defaultStr
|
||||
}
|
||||
return *originValue
|
||||
}
|
||||
|
||||
// 判断指定表达式的值,根据表达式的值返回指定的值。相当于其他语言中的三目运算符。
|
||||
func Cond[T any](expr bool, trueValue, falseValue T) T {
|
||||
if expr {
|
||||
return trueValue
|
||||
}
|
||||
return falseValue
|
||||
}
|
||||
|
||||
// 使用给定的函数对指定的值进行判断,根据表达式的值返回指定的值。
|
||||
func CondFn[T, R any](exprFn func(val T) bool, value T, trueValue, falseValue R) R {
|
||||
return Cond(exprFn(value), trueValue, falseValue)
|
||||
}
|
||||
|
||||
// 使用给定的函数对指定的值进行判断,根据表达式的值返回指定的值。本函数为惰性求值。
|
||||
func CondFnElse[T, R any](exprFn func(val T) bool, value T, trueValueFn func(val T) R, falseValueFn func(val T) R) R {
|
||||
if exprFn(value) {
|
||||
return trueValueFn(value)
|
||||
}
|
||||
return falseValueFn(value)
|
||||
}
|
||||
|
||||
// 使用给定的函数对指定的值进行判断,如果表达式为真,则返回指定的值,否则返回另一个值。
|
||||
func CondOr[T any](exprFn func(val T) bool, value, elseValue T) T {
|
||||
return CondFn(exprFn, value, value, elseValue)
|
||||
}
|
||||
|
||||
// 将指定的字符串指针解析为一个可空的`decimal.NullDecimal`类型的值。
|
||||
func NewNullDecimalFromString(val *string) (decimal.NullDecimal, error) {
|
||||
if val == nil {
|
||||
return decimal.NullDecimal{Valid: false}, nil
|
||||
}
|
||||
nd, err := decimal.NewFromString(*val)
|
||||
if err != nil {
|
||||
return decimal.NullDecimal{Valid: false}, err
|
||||
}
|
||||
return decimal.NullDecimal{Decimal: nd, Valid: true}, nil
|
||||
}
|
||||
|
||||
// 将指定的字符串指针解析为一个`decimal.Decimal`类型的值,必须提供一个默认值,以用来替换解析失败以及空指针的情况。
|
||||
func NewDecimalFromString(val *string, defaultValue decimal.Decimal) decimal.Decimal {
|
||||
if val == nil {
|
||||
return defaultValue
|
||||
}
|
||||
nd, err := decimal.NewFromString(*val)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
return nd
|
||||
}
|
||||
|
||||
// 将空白字符串转换为空指针,同时字符串本身也将转换为指针类型。
|
||||
func EmptyToNil(val string) *string {
|
||||
if len(val) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &val
|
||||
}
|
||||
|
||||
// 将一个`decimal.NullDecimal`类型的值转换为字符串指针,并且在转换的过程中设定其展示位数,默认使用银行进位法。
|
||||
func NullDecimalToString(d decimal.NullDecimal, precision ...int32) *string {
|
||||
precision = append(precision, 2)
|
||||
if !d.Valid {
|
||||
return nil
|
||||
}
|
||||
return lo.ToPtr(d.Decimal.StringFixedBank(precision[0]))
|
||||
}
|
||||
|
Reference in New Issue
Block a user