From 6d6d85bcbfc0f3b178a9c85b5961ccb960bf973f Mon Sep 17 00:00:00 2001 From: 王家文 Date: Mon, 8 Apr 2024 14:50:45 +0800 Subject: [PATCH] feat:util-lx相关库整理 --- util/util-lx/lxalilog/index.go | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util-lx/lxarray/index.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util-lx/lxconv/encry.go | 22 ++++++++++++++++++++++ util/util-lx/lxconv/index.go | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util-lx/lxconv/url.go | 17 +++++++++++++++++ util/util-lx/lxlimit/index.go | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util-lx/lxlimit/redis.go | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util-lx/lxmysql/exec.go | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util-lx/lxmysql/fx.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util-lx/lxmysql/intis.go | 36 ++++++++++++++++++++++++++++++++++++ util/util-lx/lxmysql/query.go | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util-lx/lxtime/index.go | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 1528 insertions(+), 0 deletions(-) create mode 100644 util/util-lx/lxalilog/index.go create mode 100644 util/util-lx/lxarray/index.go create mode 100644 util/util-lx/lxconv/encry.go create mode 100644 util/util-lx/lxconv/index.go create mode 100644 util/util-lx/lxconv/url.go create mode 100644 util/util-lx/lxlimit/index.go create mode 100644 util/util-lx/lxlimit/redis.go create mode 100644 util/util-lx/lxmysql/exec.go create mode 100644 util/util-lx/lxmysql/fx.go create mode 100644 util/util-lx/lxmysql/intis.go create mode 100644 util/util-lx/lxmysql/query.go create mode 100644 util/util-lx/lxtime/index.go diff --git a/util/util-lx/lxalilog/index.go b/util/util-lx/lxalilog/index.go new file mode 100644 index 0000000..9bcfee1 --- /dev/null +++ b/util/util-lx/lxalilog/index.go @@ -0,0 +1,269 @@ +package lxalilog + +import ( + "fmt" + "os" + "os/signal" + "runtime" + "strings" + "time" + + sls "github.com/aliyun/aliyun-log-go-sdk" + + "github.com/aliyun/aliyun-log-go-sdk/producer" + "github.com/astaxie/beego/logs" + lconv "github.com/lixu-any/go-tools/conv" + ltime "github.com/lixu-any/go-tools/time" +) + +var ( + LXAliProducer *producer.Producer + LXAliDefaultConfig MapAlilogConfig //默认配置 +) + +type MapAlilogConfig struct { + Endpoint string + AccessKeyId string + AppNaame string + AccessKeySecret string + Project string + On string + Debug string + + TableError string + TableDebug string + Env string +} + +// 初始化阿里云日志 +func InitAliLog(config MapAlilogConfig) { + + LXAliDefaultConfig = config + + if config.On != "1" { + return + } + + producerConfig := producer.GetDefaultProducerConfig() + + producerConfig.Endpoint = config.Endpoint + producerConfig.AccessKeyID = config.AccessKeyId + producerConfig.AccessKeySecret = config.AccessKeySecret + + LXAliProducer = producer.InitProducer(producerConfig) + + ch := make(chan os.Signal) + + signal.Notify(ch) + + LXAliProducer.Start() + + //LXAliProducer.SafeClose() // 安全关闭 +} + +func FormatLog(f interface{}, v ...interface{}) string { + return formatLog(f, v) +} + +func formatLog(f interface{}, v ...interface{}) string { + var msg string + switch f := f.(type) { + case string: + msg = f + if len(v) == 0 { + return msg + } + if strings.Contains(msg, "%") && !strings.Contains(msg, "%%") { + //format string + } else { + //do not contain format char + msg += strings.Repeat(" %v", len(v)) + } + default: + msg = fmt.Sprint(f) + if len(v) == 0 { + return msg + } + msg += strings.Repeat(" %v", len(v)) + } + return fmt.Sprintf(msg, v...) +} + +// 写日志到阿里云 +func Writelog(s string, topic string, ip string, config map[string]string) (err error) { + + if LXAliDefaultConfig.On != "1" { + return + } + + if LXAliDefaultConfig.Env != "" { + config["env"] = LXAliDefaultConfig.Env + } + + log := producer.GenerateLog(uint32(time.Now().Unix()), config) + + err = LXAliProducer.SendLog(LXAliDefaultConfig.Project, s, topic, ip, log) + + if err != nil { + return + } + + return + +} + +// 获取正在运行的函数名 +func runFuncName(l int) (string, string, int) { + + pc, file, line, _ := runtime.Caller(l) + + name := runtime.FuncForPC(pc).Name() + + split := strings.Split(name, ".") + + funname := split[len(split)-1] + + return funname, file, line +} + +// ErrorCode 错误日志 +func ErrorCode(code interface{}, v ...interface{}) { + + funname, file, line := runFuncName(3) + + logd := make(map[string]string) + + logd["fun"] = funname + + logd["file"] = file + + logd["app"] = LXAliDefaultConfig.AppNaame + + logd["line"] = fmt.Sprintf("%d", line) + + logd["msg"] = formatLog(code, v) + + logd["time"] = lconv.Int64ToStr(ltime.UninxTime()) + + logs.Error("file::", file, ",line::", line, ",fun::", funname, "[", logd["msg"], "],time::", logd["time"]) + + if LXAliDefaultConfig.TableError != "" { + go Writelog(LXAliDefaultConfig.TableError, funname, "127.0.0.1", logd) + } + +} + +// 错误日志 +func Errors(f interface{}, v ...interface{}) { + + funname, file, line := runFuncName(2) + + logd := make(map[string]string) + + logd["fun"] = funname + + logd["file"] = file + + logd["app"] = LXAliDefaultConfig.AppNaame + + logd["line"] = fmt.Sprintf("%d", line) + + logd["msg"] = formatLog(f, v) + + logd["time"] = lconv.Int64ToStr(ltime.UninxTime()) + + logs.Error("file::", file, ",line::", line, ",fun::", funname, "[", logd["msg"], "],time::", logd["time"]) + + if LXAliDefaultConfig.TableError != "" { + go Writelog(LXAliDefaultConfig.TableError, funname, "127.0.0.1", logd) + } + +} + +// 调试日志 +func Debug(f interface{}, v ...interface{}) { + + funname, file, line := runFuncName(2) + + logd := make(map[string]string) + + logd["fun"] = funname + + logd["file"] = file + + logd["app"] = LXAliDefaultConfig.AppNaame + + logd["line"] = fmt.Sprintf("%d", line) + + logd["msg"] = formatLog(f, v) + + logd["time"] = lconv.Int64ToStr(ltime.UninxTime()) + + logs.Debug("file::", file, ",line::", line, ",fun::", funname, "[", logd["msg"], "],time::", logd["time"]) + + if LXAliDefaultConfig.Debug == "1" && LXAliDefaultConfig.TableDebug != "" { + go Writelog(LXAliDefaultConfig.TableDebug, funname, "127.0.0.1", logd) + } +} + +type LogParams struct { + Project string + PowerSql bool +} + +// 查询日志 +func GetLog(logname, sql string, starttime, endtime int64, nums int64, p ...LogParams) (lst []map[string]string, err error) { + + var dproject = LXAliDefaultConfig.Project + + if len(p) > 0 { + if p[0].Project != "" { + dproject = p[0].Project + } + } + + // 创建日志服务Client。 + client := sls.CreateNormalInterface(LXAliDefaultConfig.Endpoint, LXAliDefaultConfig.AccessKeyId, LXAliDefaultConfig.AccessKeySecret, "") + + resp, err := client.GetLogs(dproject, logname, "", starttime, endtime, sql, nums, 0, true) + if err != nil { + return + } + + logs := resp.Logs + for i := range logs { + var item = make(map[string]string) + for k, v := range logs[i] { + item[k] = v + } + lst = append(lst, item) + } + + return +} + +func GetLog1(logname, sql string, starttime, endtime int64, nums int64, pas int64) (lst []map[string]string, err error) { + + // 创建日志服务Client。 + client := sls.CreateNormalInterface(LXAliDefaultConfig.Endpoint, LXAliDefaultConfig.AccessKeyId, LXAliDefaultConfig.AccessKeySecret, "") + + resp, err := client.GetLogs(LXAliDefaultConfig.Project, logname, "", starttime, endtime, sql, nums, pas*nums, true) + if err != nil { + return + } + + logs := resp.Logs + for i := range logs { + var item = make(map[string]string) + for k, v := range logs[i] { + item[k] = v + } + lst = append(lst, item) + } + + return +} + +func GetLogV2(logname, sql string, starttime, endtime int64, nums int64, pas int64) (lst []map[string]string, err error) { + return GetLog1(logname, sql, starttime, endtime, nums, pas) +} diff --git a/util/util-lx/lxarray/index.go b/util/util-lx/lxarray/index.go new file mode 100644 index 0000000..0b763cf --- /dev/null +++ b/util/util-lx/lxarray/index.go @@ -0,0 +1,71 @@ +package lxarray + +// InArray 判断字符串在数组内 +func InArray(s string, d []string) bool { + for _, v := range d { + if s == v { + return true + } + } + return false +} + +// SplitArray sources源数组,num拆分份数,size每份的大小 +func SplitArray(sources []string, num, pageSize int64) [][]string { + max := int64(len(sources)) + if max < num { + return nil + } + var segmens = make([][]string, 0) + quantity := pageSize + end := int64(0) + for i := int64(1); i <= num; i++ { + qu := i * quantity + if i != num { + segmens = append(segmens, sources[i-1+end:qu]) + } else { + segmens = append(segmens, sources[i-1+end:]) + } + end = qu - i + } + return segmens +} + +// SplitArrayCnt sourceslen源数组长度,pageSize页数据量 +func SplitArrayCnt(sourceslen, pageSize int) int { + if sourceslen < pageSize { + return 1 + } + s := sourceslen / pageSize + y := sourceslen % pageSize + if y > 0 { + return s + 1 + } else { + return s + } +} + +// DeleteRepeatString 数组去重 +func DeleteRepeatString(arr []string) []string { + // 创建一个新的切片,用于存储去重后的元素 + result := make([]string, 0, len(arr)) + // 遍历原始数组 + for _, item := range arr { + // 如果元素不在结果切片中,则将其添加到结果切片中 + if !containsString(result, item) { + result = append(result, item) + } + } + return result +} + +func containsString(arr []string, se string) bool { + // 遍历结果切片 + for _, n := range arr { + // 如果找到匹配的元素,则返回 true + if n == se { + return true + } + } + return false +} diff --git a/util/util-lx/lxconv/encry.go b/util/util-lx/lxconv/encry.go new file mode 100644 index 0000000..9727cb3 --- /dev/null +++ b/util/util-lx/lxconv/encry.go @@ -0,0 +1,22 @@ +package lxconv + +import ( + "crypto/md5" + "crypto/sha1" + "encoding/hex" + "fmt" +) + +// EncryMD5 MD5 字符串 +func EncryMD5(text string) string { + ctx := md5.New() + ctx.Write([]byte(text)) + return hex.EncodeToString(ctx.Sum(nil)) +} + +// EncrySHA1 SHA1 字符串 +func EncrySHA1(text string) string { + ctx := sha1.New() + ctx.Write([]byte(text)) + return fmt.Sprintf("%x", ctx.Sum(nil)) +} diff --git a/util/util-lx/lxconv/index.go b/util/util-lx/lxconv/index.go new file mode 100644 index 0000000..24af42b --- /dev/null +++ b/util/util-lx/lxconv/index.go @@ -0,0 +1,245 @@ +package lxconv + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" +) + +// IntToStr 数字转换字符串 +func IntToStr(i int) string { + return strconv.Itoa(i) +} + +// Int64ToStr 64位数字转换字符串 +func Int64ToStr(i int64) string { + return strconv.FormatInt(i, 10) +} + +// StrToInt 字符串转换位int +func StrToInt(str string) int { + intnum, _ := strconv.Atoi(str) + return intnum +} + +// StrToInt64 字符串转换位int64 +func StrToInt64(str string) int64 { + intnum, _ := strconv.ParseInt(str, 10, 64) + return intnum +} + +// StrToFloat64 字符串转换浮点数 +func StrToFloat64(str string, i int) float64 { + v2, _ := strconv.ParseFloat(str, i) + return v2 +} + +// ParseInt64 字符串转换位int64 +func ParseInt64(val interface{}) int64 { + + if val == nil { + return 0 + } + + switch ret := val.(type) { + case string: + return StrToInt64(ret) + case int8: + return int64(ret) + case uint8: + return int64(ret) + case int16: + return int64(ret) + case uint16: + return int64(ret) + case int: + return int64(ret) + case uint: + return int64(ret) + case int64: + return int64(ret) + case uint64: + return int64(ret) + case float32: + return int64(ret) + case float64: + return int64(ret) + } + + return 0 +} + +// ParseInt 字符串转换位int +func ParseInt(val interface{}) int { + + if val == nil { + return 0 + } + + switch ret := val.(type) { + case string: + return StrToInt(ret) + case int8: + return int(ret) + case uint8: + return int(ret) + case int16: + return int(ret) + case uint16: + return int(ret) + case int: + return int(ret) + case uint: + return int(ret) + case int64: + return int(ret) + case uint64: + return int(ret) + case float32: + return int(ret) + case float64: + return int(ret) + } + + return 0 +} + +// FloatTostr 浮点数转换int卡类型 +func FloatTostr(floatstr float64, i int) string { + return strconv.FormatFloat(floatstr, 'E', -1, i) +} + +// JsonEncode json转字符串 +func JsonEncode(data interface{}) string { + datastr, _ := json.Marshal(data) + return string(datastr) +} + +// ToInt 任意类型强转int +func ToInt(a interface{}) int { + + ai := 0 + + switch a := a.(type) { + case float64: + ai = int(a) + case float32: + ai = int(a) + case int: + ai = a + case int32: + ai = int(a) + case int64: + ai = int(a) + case string: + ai = StrToInt(a) + + default: + + } + + return ai +} + +// ToInt64 任意类型强转int64 +func ToInt64(a interface{}) int64 { + + var ai int64 + + switch a := a.(type) { + case float64: + ai = int64(a) + case float32: + ai = int64(a) + case int: + ai = int64(a) + case int32: + ai = int64(a) + case int64: + ai = a + case string: + ai = StrToInt64(a) + + default: + + } + + return ai +} + +// ToFloat64 任意类型强转float64 +func ToFloat64(a interface{}) float64 { + + var ai float64 + + switch a := a.(type) { + case float64: + ai = a + case float32: + ai = float64(a) + case int: + ai = float64(a) + case int32: + ai = float64(a) + case int64: + ai = float64(a) + case string: + ai = StrToFloat64(a, 64) + + default: + + } + + return ai +} + +// ToString 任意类型强转字符串 +func ToString(a interface{}) string { + + var ai string + + switch a := a.(type) { + case float64: + ai = strconv.FormatFloat(a, 'E', -1, 64) + case float32: + ai = strconv.FormatFloat(float64(a), 'E', -1, 64) + case int: + ai = fmt.Sprintf("%d", a) + case int32: + ai = fmt.Sprintf("%d", a) + case int64: + ai = fmt.Sprintf("%d", a) + case string: + ai = fmt.Sprintf("%s", a) + default: + ai = fmt.Sprintf("%v", a) + + } + + return ai +} + +func InterfaceToStr(v interface{}) string { + str := "" + switch v.(type) { + case string: + str = v.(string) + default: + jsonbyte, _ := json.Marshal(v) + str = string(jsonbyte) + } + return str +} + +// ToBool 转换 bool类型 +func ToBool(a interface{}) bool { + + s := ToString(a) + if s == "1" || strings.ToLower(s) == "true" { + return true + } + + return false + +} diff --git a/util/util-lx/lxconv/url.go b/util/util-lx/lxconv/url.go new file mode 100644 index 0000000..fa8c995 --- /dev/null +++ b/util/util-lx/lxconv/url.go @@ -0,0 +1,17 @@ +package lxconv + +import ( + "net/url" + "strings" +) + +func UrlEncode(str string) string { + encodeurl := url.QueryEscape(str) + encodeurl = strings.ReplaceAll(encodeurl, "\"", "%22") + return encodeurl +} + +func UrlDecode(str string) string { + decodeurl, _ := url.QueryUnescape(str) + return decodeurl +} diff --git a/util/util-lx/lxlimit/index.go b/util/util-lx/lxlimit/index.go new file mode 100644 index 0000000..194729c --- /dev/null +++ b/util/util-lx/lxlimit/index.go @@ -0,0 +1,267 @@ +package lxlimit + +import ( + "apigame/lx-util/lxconv" + "encoding/json" + "fmt" + "github.com/astaxie/beego/logs" + redigo "github.com/garyburd/redigo/redis" + "hash/fnv" + "strconv" + "strings" +) + +// api限流 +// 创建时间:2023/11/24 11:23 +// 创建人:lixu + +type LimitConfig struct { + Redis MapRedisConfig `json:"redis"` + Func MFuncConfig `json:"func"` +} + +type MFuncItem struct { + Name string `json:"name"` + Times int `json:"times"` // 每几秒 + Nums int `json:"nums"` // 限制多少次 +} + +type MFuncConfig struct { + FunName string `json:"fun_name"` + Open bool `json:"open"` + Ip MFuncItem `json:"ip"` + Kernel MFuncItem `json:"kernel"` + BodyBy []byte `json:"bodyBy"` + Url string `json:"url"` + Params map[string]string `json:"params"` + DelGameIDS []string `json:"delGameIDS"` // 删除某个游戏 + Member MFuncItem `json:"member"` +} + +type LimitVar struct { + RedisConfig MapRedisConfig + RedisPool *redigo.Pool + FuncConfig MFuncConfig +} + +var LXLIMITCL LimitVar + +// InitDefault 初始化 +func InitDefault(cfg LimitConfig) (err error) { + + err = initRedis(cfg.Redis) + if err != nil { + logs.Error("InitDefault", "initRedis error::", err) + return + } + + LXLIMITCL.FuncConfig = cfg.Func + + return +} + +// CheckLimit 检查是否超 出限制 +func CheckLimit(cfg MFuncConfig) (gameid, tp string) { + var ( + times = 0 + postdata map[string]interface{} + ) + + postdata = make(map[string]interface{}) + + if len(cfg.BodyBy) > 0 { + _ = json.Unmarshal([]byte(cfg.BodyBy), &postdata) + if postdata["gameid"] != nil { + gameid = lxconv.ToString(postdata["gameid"]) + } + } + + if !LXLIMITCL.FuncConfig.Open || cfg.FunName == "" { + return + } + + if len(cfg.DelGameIDS) > 0 { + + if cfg.Url != "" { + for _, gameid := range cfg.DelGameIDS { + if strings.Contains(cfg.Url, gameid) { + tp = "gameid" + break + } + } + if tp != "" { + return + } + } + + if postdata["gameid"] != nil { + pgameid := lxconv.ToString(postdata["gameid"]) + for _, gid := range cfg.DelGameIDS { + if pgameid == gid { + tp = "gameid" + break + } + } + if tp != "" { + return + } + } + } + + if cfg.Ip.Name != "" { + if cfg.Ip.Times == 0 { + cfg.Ip.Times = LXLIMITCL.FuncConfig.Ip.Times + } + if cfg.Ip.Nums == 0 { + cfg.Ip.Nums = LXLIMITCL.FuncConfig.Ip.Nums + } + } + + if cfg.Kernel.Name != "" { + if cfg.Kernel.Times == 0 { + cfg.Kernel.Times = LXLIMITCL.FuncConfig.Kernel.Times + } + if cfg.Kernel.Nums == 0 { + cfg.Kernel.Nums = LXLIMITCL.FuncConfig.Kernel.Nums + } + } + + if cfg.Member.Times == 0 { + cfg.Member.Times = LXLIMITCL.FuncConfig.Member.Times + } + if cfg.Member.Nums == 0 { + cfg.Member.Nums = LXLIMITCL.FuncConfig.Member.Nums + } + + _rds := LXredis{} + + ipif := (cfg.Ip.Times > 0 && cfg.Ip.Name != "") + + if ipif { + _rds.Name = "ip::" + cfg.Ip.Name + _rds.Name += getRedisKey(cfg.FunName, cfg.Ip.Name) + // ip + if isx, _ := _rds.IsExist(); isx { + gstr, _ := _rds.GET() + if gstr != "" { + times, _ = strconv.Atoi(gstr) + if times >= cfg.Ip.Nums { + tp = "ip" + return + } + } + _rds.INCR() + //logs.Error("ip:::11::", lxconv.JsonEncode(cfg.Ip)) + } else { + //logs.Error("ip:::22::", lxconv.JsonEncode(cfg.Ip)) + _rds.Val = "1" + _rds.setTime(cfg.Ip.Times) + } + + ex, _ := _rds.TTL() + if ex < 0 { + _rds.EXPIRE(cfg.Ip.Times) + } + + } + + if ipif && cfg.Kernel.Times > 0 && cfg.Kernel.Name != "" { + _rds.Name = "kernel::" + cfg.Ip.Name + _rds.Name += getRedisKey(cfg.FunName, cfg.Ip.Name, cfg.Kernel.Name) + // ip + if isx, _ := _rds.IsExist(); isx { + gstr, _ := _rds.GET() + if gstr != "" { + times, _ = strconv.Atoi(gstr) + if times >= cfg.Kernel.Nums { + tp = "kernel" + return + } + } + _rds.INCR() + //logs.Error("Kernel:::11::", lxconv.JsonEncode(cfg.Kernel)) + } else { + _rds.Val = "1" + _rds.setTime(cfg.Kernel.Times) + //logs.Error("Kernel:::22::", lxconv.JsonEncode(cfg.Kernel)) + } + + ex, _ := _rds.TTL() + if ex < 0 { + _rds.EXPIRE(cfg.Kernel.Times) + } + + } + + var uid string + + if cfg.Member.Name != "" { + if strings.Contains(cfg.Member.Name, "{gameid}") && postdata["gameid"] != nil { + gameid = lxconv.InterfaceToStr(postdata["gameid"]) + cfg.Member.Name = strings.Replace(cfg.Member.Name, "{gameid}", gameid, -1) + } + + if strings.Contains(cfg.Member.Name, "{uid}") && postdata["uid"] != nil { + uid = lxconv.InterfaceToStr(postdata["uid"]) + cfg.Member.Name = strings.Replace(cfg.Member.Name, "{uid}", uid, -1) + } + } + + if cfg.Member.Times > 0 && cfg.Member.Name != "" { + _rds.Name = "member::" + cfg.Member.Name + _rds.Name += getRedisKey(cfg.FunName) + // ip + if isx, _ := _rds.IsExist(); isx { + gstr, _ := _rds.GET() + if gstr != "" { + times, _ = strconv.Atoi(gstr) + if times >= cfg.Member.Nums { + tp = "member" + return + } + } + _rds.INCR() + //logs.Error("Member:::11::", lxconv.JsonEncode(cfg.Member)) + } else { + _rds.Val = "1" + _rds.setTime(cfg.Member.Times) + //logs.Error("Member:::22::", lxconv.JsonEncode(cfg.Member)) + } + + ex, _ := _rds.TTL() + if ex < 0 { + _rds.EXPIRE(cfg.Member.Times) + } + + } + + return +} + +func hashMod(key string, modulus int) int { + // 使用FNV哈希算法计算哈希值 + hash := fnv.New32a() + hash.Write([]byte(key)) + hashValue := hash.Sum32() + + // 对哈希值取模得到结果 + result := int(hashValue % uint32(modulus)) + return result +} + +func getRedisKey(ccs ...interface{}) (k string) { + + var pms string + + for _, cc := range ccs { + pms += lxconv.InterfaceToStr(cc) + } + + mds := hashMod(pms, 100000) + + k = "::" + lxconv.EncryMD5(pms) + + k += fmt.Sprintf("%d", mds) + + return +} diff --git a/util/util-lx/lxlimit/redis.go b/util/util-lx/lxlimit/redis.go new file mode 100644 index 0000000..065a4de --- /dev/null +++ b/util/util-lx/lxlimit/redis.go @@ -0,0 +1,212 @@ +package lxlimit + +import ( + "fmt" + redigo "github.com/garyburd/redigo/redis" +) + +// redis +// 创建时间:2023/11/24 11:25 +// 创建人:lixu + +type MapRedisConfig struct { + Host string `json:"host"` + Port string `json:"port"` + Pwd string `json:"pwd"` + Db string `json:"Db"` + Prefix string `json:"prefix"` +} + +func getRedis() redigo.Conn { + return LXLIMITCL.RedisPool.Get() +} + +type LXredis struct { + Name string `json:"name"` + Val string `json:"val"` + Db string `json:"db"` + Prefix string `json:"prefix"` +} + +// initRedis 初始化Redis +func initRedis(config MapRedisConfig) (err error) { + + LXLIMITCL.RedisConfig = config + + pool_size := 20 + + LXLIMITCL.RedisPool = redigo.NewPool(func() (redigo.Conn, error) { + c, err := redigo.Dial("tcp", fmt.Sprintf("%s:%s", LXLIMITCL.RedisConfig.Host, LXLIMITCL.RedisConfig.Port)) + if err != nil { + return nil, err + } + if _, err := c.Do("AUTH", LXLIMITCL.RedisConfig.Pwd); err != nil { + c.Close() + return nil, err + } + if _, err := c.Do("SELECT", LXLIMITCL.RedisConfig.Db); err != nil { + c.Close() + return nil, err + } + + return c, nil + }, pool_size) + + return +} + +// SetTime 设置redis字符串 加过期时间 +func (con *LXredis) setTime(times int) (err error) { + + var nname string + + if con.Prefix != "" { + nname = con.Prefix + con.Name + } else { + nname = LXLIMITCL.RedisConfig.Prefix + con.Name + } + + redis := getRedis() + + defer redis.Close() + + if con.Db != "" { + if _, err = redis.Do("SELECT", con.Db); err != nil { + return + } + } + + _, err = redis.Do("set", nname, con.Val, "EX", times) + + return +} + +// GET 获取redis +func (con *LXredis) GET() (gstr string, err error) { + + var nname string + + if con.Prefix != "" { + nname = con.Prefix + con.Name + } else { + nname = LXLIMITCL.RedisConfig.Prefix + con.Name + } + + redis := getRedis() + + defer redis.Close() + + if con.Db != "" { + if _, err = redis.Do("SELECT", con.Db); err != nil { + return + } + + } + + gstr, err = redigo.String(redis.Do("GET", nname)) + + return +} + +// IsExist 判断key是否存在 +func (con *LXredis) IsExist() (isexit bool, err error) { + + var nname string + + if con.Prefix != "" { + nname = con.Prefix + con.Name + } else { + nname = LXLIMITCL.RedisConfig.Prefix + con.Name + } + + redis := getRedis() + + defer redis.Close() + + if con.Db != "" { + if _, err = redis.Do("SELECT", con.Db); err != nil { + return + } + } + + isexit, err = redigo.Bool(redis.Do("EXISTS", nname)) + return +} + +// INCR 自增 +func (con *LXredis) INCR() (nums int64, err error) { + + var nname string + + if con.Prefix != "" { + nname = con.Prefix + con.Name + } else { + nname = LXLIMITCL.RedisConfig.Prefix + con.Name + } + + redis := getRedis() + + defer redis.Close() + + if con.Db != "" { + if _, err = redis.Do("SELECT", con.Db); err != nil { + return + } + } + + nums, err = redigo.Int64(redis.Do("INCR", nname)) + + return +} + +// TTL 查看过期时间 +func (con *LXredis) TTL() (ttl int, err error) { + + var nname string + + if con.Prefix != "" { + nname = con.Prefix + con.Name + } else { + nname = LXLIMITCL.RedisConfig.Prefix + con.Name + } + + redis := getRedis() + + defer redis.Close() + + if con.Db != "" { + if _, err = redis.Do("SELECT", con.Db); err != nil { + return + } + } + + ttl, err = redigo.Int(redis.Do("ttl", nname)) + + return +} + +// EXPIRE 设置过期时间 +func (con *LXredis) EXPIRE(times int) (err error) { + + var nname string + + if con.Prefix != "" { + nname = con.Prefix + con.Name + } else { + nname = LXLIMITCL.RedisConfig.Prefix + con.Name + } + + redis := getRedis() + + defer redis.Close() + + if con.Db != "" { + if _, err = redis.Do("SELECT", con.Db); err != nil { + return + } + } + + _, err = redigo.Int(redis.Do("EXPIRE", nname, times)) + + return +} diff --git a/util/util-lx/lxmysql/exec.go b/util/util-lx/lxmysql/exec.go new file mode 100644 index 0000000..488b856 --- /dev/null +++ b/util/util-lx/lxmysql/exec.go @@ -0,0 +1,96 @@ +package lxmysql + +import ( + "github.com/astaxie/beego/orm" + "io/ioutil" + "os" + "strings" +) + +type ExecSqlConfig struct { + Sql string //表名 + TableName string //表名 + DBIndex string //指定数据库 + Orm orm.Ormer //实例化 ORM + CreaeSql string //创建表的SQL语句 + CreatePath string //创建表的SQL文件路径 +} + +func ExecSql(config ExecSqlConfig) (err error) { + + var ( + tcount int + ) + + if config.Orm == nil { + config.Orm = orm.NewOrm() + } + + if config.DBIndex == "" { + config.DBIndex = "default" + } + +RSTART: + + config.Orm.Using(config.DBIndex) + + _, err = config.Orm.Raw(config.Sql).Exec() + if err != nil { + if b := strings.Contains(err.Error(), "doesn't exist"); b && (config.CreaeSql != "" || config.CreatePath != "") && tcount == 0 { + if config.CreaeSql == "" { + config.CreaeSql, _ = readFilesql(config.CreatePath, config.TableName) + } + + //表不存在 去创建 + err = CreateTable(config.CreaeSql, config.Orm, config.DBIndex) + if err != nil { + return + } + + tcount++ + //重新执行一次 + goto RSTART + } + + return + + } + + return +} + +func CreateTable(csql string, o orm.Ormer, dbindex string) (err error) { + + o.Using(dbindex) + + _, err = o.Raw(csql).Exec() + if err != nil { + return + } + + return +} + +func readFilesql(pth, tbname string) (sql string, err error) { + filePtr, err := os.Open(pth) + if err != nil { + return + } + defer filePtr.Close() + + by, err := ioutil.ReadAll(filePtr) + if err != nil { + return + } + + sql = strings.Replace(string(by), "{tablename}", tbname, -1) + + return +} + +func ReadFilesql(pth, tbname string) (sql string, err error) { + + pth += ".sql" + + return readFilesql(pth, tbname) +} diff --git a/util/util-lx/lxmysql/fx.go b/util/util-lx/lxmysql/fx.go new file mode 100644 index 0000000..df59132 --- /dev/null +++ b/util/util-lx/lxmysql/fx.go @@ -0,0 +1,55 @@ +package lxmysql + +import ( + "apigame/lx-util/lxconv" + lconv "github.com/lixu-any/go-tools/conv" +) + +// HashCode 计算 SQL 语句的哈希码 +func HashCode(sql string, args []interface{}) int { + hash := 17 + hash = hash*31 + len(sql) + for _, arg := range args { + hash = hash*31 + HashCodeOfArg(arg) + } + return hash +} + +// HashCodeOfArg 计算参数的哈希码 +func HashCodeOfArg(arg interface{}) int { + switch v := arg.(type) { + case int: + return v + case int8: + return int(v) + case int16: + return int(v) + case int32: + return int(v) + case int64: + return int(v) + case uint: + return int(v) + case uint8: + return int(v) + case uint16: + return int(v) + case uint32: + return int(v) + case uint64: + return int(v) + case float32: + return int(v) + case float64: + return int(v) + case string: + return len(v) + default: + return 0 + } +} + +// GenCacheKey 生成缓存名字 +func GenCacheKey(sql string, args []interface{}) string { + return lxconv.EncryMD5(sql + lconv.JsonEncode(args)) +} diff --git a/util/util-lx/lxmysql/intis.go b/util/util-lx/lxmysql/intis.go new file mode 100644 index 0000000..5d72cdc --- /dev/null +++ b/util/util-lx/lxmysql/intis.go @@ -0,0 +1,36 @@ +package lxmysql + +import ( + "github.com/astaxie/beego/orm" + _ "github.com/go-sql-driver/mysql" +) + +const ( + DEFAULT_EXPIRE = 300 //默认缓存5分钟 + DEFAULT_MAXCOUNT = 100 //默认最大条数 +) + +type MapMysqlConn struct { + Name string + SqlCon string +} + +// InitMysqls 初始化MySQL +func InitMysqls(conns []MapMysqlConn, cachedb string) (err error) { + + LXMYSQLCACHEDB = cachedb + + err = orm.RegisterDriver("mysql", orm.DRMySQL) + if err != nil { + return + } + + for _, v := range conns { + err = orm.RegisterDataBase(v.Name, "mysql", v.SqlCon) + if err != nil { + return + } + } + + return +} diff --git a/util/util-lx/lxmysql/query.go b/util/util-lx/lxmysql/query.go new file mode 100644 index 0000000..5981781 --- /dev/null +++ b/util/util-lx/lxmysql/query.go @@ -0,0 +1,132 @@ +package lxmysql + +import ( + "apigame/lx-util/lxredis" + "encoding/json" + "github.com/astaxie/beego/orm" + lconv "github.com/lixu-any/go-tools/conv" + "strings" +) + +var LXMYSQLCACHEDB string //默认缓存数据库 + +type QueryCacheConfig struct { + SQL string //sql + DBIndex string //指定数据库 + CacheDB string //数据库缓存 Redis数据库索引 + CacheName string //缓存的名字 + Orm orm.Ormer //实例化 ORM + Exexpire int //缓存过期时间 -1不使用缓存 +} + +type QueryConfig struct { + SQL string //sql + DBIndex string //指定数据库 + Orm orm.Ormer //实例化 ORM +} + +// QueryWithCache 查询数据 +func QueryWithCache(config QueryCacheConfig, result interface{}, args ...interface{}) (err error) { + + var cacheKey string + + if len(config.CacheName) > 0 { + cacheKey = config.CacheName + } else { + cacheKey = "mysql::" + GenCacheKey(config.SQL, args) + } + + if config.Exexpire == 0 { + config.Exexpire = DEFAULT_EXPIRE + } + + if config.CacheDB == "" { + config.CacheDB = LXMYSQLCACHEDB + } + + _redis := lxredis.LXredis{ + Name: cacheKey, + Db: config.CacheDB, + } + + if config.Exexpire > 0 { + if b, _ := _redis.IsExist(); b { + str, _ := _redis.GET() + if str != "" { + // 如果缓存中有数据,则直接返回数据 + err = json.Unmarshal([]byte(str), result) + if err == nil { + return + } + } + } + } + + if config.Orm == nil { + config.Orm = orm.NewOrm() + } + + if len(config.DBIndex) > 0 { + config.Orm.Using(config.DBIndex) + } + + if _, err = config.Orm.Raw(config.SQL).QueryRows(result); err != nil { + + if strings.Contains(err.Error(), "doesn't exist") { + err = nil + return + } + return + } + + if config.Exexpire > 0 { + _redis.Val = lconv.JsonEncode(result) + _redis.SetTime(config.Exexpire) + } + + return +} + +// Query 查询数据 +func Query(config QueryConfig, result interface{}, args ...interface{}) (err error) { + + if config.Orm == nil { + config.Orm = orm.NewOrm() + } + + if len(config.DBIndex) > 0 { + config.Orm.Using(config.DBIndex) + } + + if _, err = config.Orm.Raw(config.SQL).QueryRows(result); err != nil { + if strings.Contains(err.Error(), "doesn't exist") { + err = nil + return + } + return + } + + return +} + +// FindOne 查询一条数据 +func FindOne(config QueryConfig, result interface{}, args ...interface{}) (err error) { + + if config.Orm == nil { + config.Orm = orm.NewOrm() + } + + if len(config.DBIndex) > 0 { + config.Orm.Using(config.DBIndex) + } + + if err = config.Orm.Raw(config.SQL).QueryRow(result); err != nil { + if strings.Contains(err.Error(), "doesn't exist") { + err = nil + return + } + return + } + + return +} diff --git a/util/util-lx/lxtime/index.go b/util/util-lx/lxtime/index.go new file mode 100644 index 0000000..4d2cb28 --- /dev/null +++ b/util/util-lx/lxtime/index.go @@ -0,0 +1,106 @@ +package lxtime + +import ( + "fmt" + "time" +) + +// NowUninx 当前的时间戳 (秒) +func NowUninx() int64 { + return time.Now().Unix() +} + +//// NowUnixMilli 当前的时间戳 (毫秒) +//func NowUnixMilli() int64 { +// return time.Now().UnixMilli() +//} + +//// NowUnixMicro 当前的时间戳 (微秒) +//func NowUnixMicro() int64 { +// return time.Now().UnixMicro() +//} + +// NowUnixNano 当前的时间戳 (纳秒) +func NowUnixNano() int64 { + return time.Now().UnixNano() +} + +// NowDate 当前日期字符串 +func NowDate() string { + return GetDate(NowUninx()) +} + +// NowTime 当前时间字符串 +func NowTime() string { + return GetTime(NowUninx()) +} + +// NowYear 当前时间字符串 年 +func NowYear() string { + return GetYear(NowUninx()) +} + +// NowMonth 当前时间字符串 月 +func NowMonth() string { + return GetMonth(NowUninx()) +} + +// NowDay 当前时间字符串 日 +func NowDay() string { + return GetDay(NowUninx()) +} + +// NowDateTime 当前日期时间字符串 +func NowDateTime() string { + return GetDateTime(NowUninx()) +} + +// NowZeroUninxTime 0点的时间戳 +func NowZeroUninxTime() int64 { + tim := time.Unix(NowUninx(), 0).Format("2006-01-02") + t, _ := time.ParseInLocation("2006-01-02 15:04:05", tim+" 00:00:00", time.Local) + return t.Unix() +} + +// GetDate 时间戳转换 日期字符串 +func GetDate(utime int64) string { + tim := time.Unix(utime, 0).Format("2006-01-02") + return fmt.Sprintf("%s", tim) +} + +// GetTime 时间戳转换 时间字符串 +func GetTime(utime int64) string { + tim := time.Unix(utime, 0).Format("15:04:05") + return fmt.Sprintf("%s", tim) +} + +// GetDateTime 时间戳转换 日期时间字符串 +func GetDateTime(utime int64) string { + tim := time.Unix(utime, 0).Format("2006-01-02 15:04:05") + return fmt.Sprintf("%s", tim) +} + +// GetMonth 时间戳转换 月 +func GetMonth(utime int64) string { + tim := time.Unix(utime, 0).Format("01") + return fmt.Sprintf("%s", tim) +} + +// GetYear 时间戳转换 年 +func GetYear(utime int64) string { + tim := time.Unix(utime, 0).Format("2006") + return fmt.Sprintf("%s", tim) +} + +// GetDay 时间戳转换 日 +func GetDay(utime int64) string { + tim := time.Unix(utime, 0).Format("02") + return fmt.Sprintf("%s", tim) +} + +// GetZeroUninxTime 计算0点的时间戳 +func GetZeroUninxTime(utime int64) int64 { + tim := time.Unix(utime, 0).Format("2006-01-02") + t, _ := time.ParseInLocation("2006-01-02 15:04:05", tim+" 00:00:00", time.Local) + return t.Unix() +} -- libgit2 0.21.0