合并分支

This commit is contained in:
2023-08-04 17:11:10 +08:00
parent 12ec8d26bf
commit 020e76b901
100 changed files with 12692 additions and 2574 deletions

84
tools/serial/algorithm.go Normal file
View 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 ""
}

View File

@@ -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]))
}