From 8c0aa6c2ae08951a90460e01222c7ee69b446b00 Mon Sep 17 00:00:00 2001 From: vipg Date: Fri, 6 Feb 2026 16:51:09 +0800 Subject: [PATCH] add --- trading_assistant_api/common/go.mod | 2 +- trading_assistant_api/common/utils/common.go | 276 +++++++++++++++++++ 2 files changed, 277 insertions(+), 1 deletion(-) diff --git a/trading_assistant_api/common/go.mod b/trading_assistant_api/common/go.mod index 7469f1f..28206fa 100644 --- a/trading_assistant_api/common/go.mod +++ b/trading_assistant_api/common/go.mod @@ -1,4 +1,4 @@ -module code/common +module common go 1.25.7 diff --git a/trading_assistant_api/common/utils/common.go b/trading_assistant_api/common/utils/common.go index e69de29..816483f 100644 --- a/trading_assistant_api/common/utils/common.go +++ b/trading_assistant_api/common/utils/common.go @@ -0,0 +1,276 @@ +// common/common.go +package common + +import ( + "crypto/rand" + "encoding/base64" + "errors" + "fmt" + "math/big" + "os" + "reflect" + "strconv" + "strings" + "time" +) + +// ---------------------- 环境变量操作 ---------------------- +// 项目中最常用的通用能力,适配Docker容器化(环境变量传配置) +// GetEnv 读取环境变量,若不存在则返回默认值 +func GetEnv(key, defVal string) string { + val := os.Getenv(key) + if val == "" { + return defVal + } + return val +} + +// GetEnvInt 读取环境变量并转换为int,转换失败/不存在返回默认值 +func GetEnvInt(key string, defVal int) int { + val := os.Getenv(key) + if val == "" { + return defVal + } + num, err := strconv.Atoi(val) + if err != nil { + return defVal + } + return num +} + +// GetEnvBool 读取环境变量并转换为bool(支持1/0、true/false、on/off),失败/不存在返回默认值 +func GetEnvBool(key string, defVal bool) bool { + val := strings.ToLower(os.Getenv(key)) + switch val { + case "1", "true", "on": + return true + case "0", "false", "off": + return false + default: + return defVal + } +} + +// ---------------------- 类型转换 ---------------------- +// 日常开发中频繁的类型转换,封装后避免重复写err判断 +// StrToInt 字符串转int,失败返回0和错误 +func StrToInt(s string) (int, error) { + return strconv.Atoi(s) +} + +// StrToInt64 字符串转int64,失败返回0和错误 +func StrToInt64(s string) (int64, error) { + return strconv.ParseInt(s, 10, 64) +} + +// IntToStr int转字符串 +func IntToStr(i int) string { + return strconv.Itoa(i) +} + +// Int64ToStr int64转字符串 +func Int64ToStr(i int64) string { + return strconv.FormatInt(i, 10) +} + +// StrToFloat64 字符串转float64,失败返回0和错误 +func StrToFloat64(s string) (float64, error) { + return strconv.ParseFloat(s, 64) +} + +// Float64ToStr float64转字符串,保留n位小数 +func Float64ToStr(f float64, n int) string { + format := fmt.Sprintf("%%.%df", n) + return fmt.Sprintf(format, f) +} + +// ---------------------- 时间通用处理 ---------------------- +// 统一项目时间格式,避免各业务自定义格式导致的混乱 +const ( + // TimeFormatYmdHms 常规时间格式:2006-01-02 15:04:05(Go诞生时间,固定模板) + TimeFormatYmdHms = "2006-01-02 15:04:05" + // TimeFormatYmd 日期格式:2006-01-02 + TimeFormatYmd = "2006-01-02" + // TimeFormatHms 时间格式:15:04:05 + TimeFormatHms = "15:04:05" + // TimeFormatYmdHmsS 带毫秒的时间格式:2006-01-02 15:04:05.000 + TimeFormatYmdHmsS = "2006-01-02 15:04:05.000" +) + +// TimeToStr 时间转字符串,指定格式(不传则用默认YmdHms) +func TimeToStr(t time.Time, format ...string) string { + ft := TimeFormatYmdHms + if len(format) > 0 && format[0] != "" { + ft = format[0] + } + // 转换为本地时区(避免UTC时间偏移) + return t.In(time.Local).Format(ft) +} + +// NowToStr 当前时间转字符串,指定格式(不传则用默认YmdHms) +func NowToStr(format ...string) string { + return TimeToStr(time.Now(), format...) +} + +// StrToTime 字符串转时间,指定格式(不传则用默认YmdHms),失败返回零值和错误 +func StrToTime(s string, format ...string) (time.Time, error) { + ft := TimeFormatYmdHms + if len(format) > 0 && format[0] != "" { + ft = format[0] + } + return time.ParseInLocation(ft, s, time.Local) +} + +// GetDayStart 获取某天的开始时间(如2026-02-06 00:00:00) +func GetDayStart(t time.Time) time.Time { + year, month, day := t.In(time.Local).Date() + return time.Date(year, month, day, 0, 0, 0, 0, time.Local) +} + +// GetDayEnd 获取某天的结束时间(如2026-02-06 23:59:59.999999999) +func GetDayEnd(t time.Time) time.Time { + year, month, day := t.In(time.Local).Date() + return time.Date(year, month, day, 23, 59, 59, 999999999, time.Local) +} + +// ---------------------- 空值判断 ---------------------- +// 通用的空值检查,支持所有基础类型和引用类型,避免业务层重复写if判断 +// IsEmpty 判断值是否为空(0/""//nil/空切片/空map等) +func IsEmpty(v interface{}) bool { + if v == nil { + return true + } + val := reflect.ValueOf(v) + switch val.Kind() { + case reflect.String: + return val.String() == "" + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return val.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return val.Uint() == 0 + case reflect.Float32, reflect.Float64: + return val.Float() == 0 + case reflect.Bool: + return !val.Bool() + case reflect.Slice, reflect.Array: + return val.Len() == 0 + case reflect.Map, reflect.Chan: + return val.Len() == 0 || val.IsNil() + case reflect.Ptr, reflect.Interface: + return val.IsNil() + default: + return false + } +} + +// IsNotEmpty 判断值是否非空,与IsEmpty相反 +func IsNotEmpty(v interface{}) bool { + return !IsEmpty(v) +} + +// ---------------------- 字符串通用处理 ---------------------- +// 高频的字符串操作,封装后简化调用 +// StrTrim 去除字符串两端的空格/制表符/换行符 +func StrTrim(s string) string { + return strings.TrimSpace(s) +} + +// StrToLower 字符串转小写 +func StrToLower(s string) string { + return strings.ToLower(s) +} + +// StrToUpper 字符串转大写 +func StrToUpper(s string) string { + return strings.ToUpper(s) +} + +// StrIsIn 判断字符串是否在指定的切片中(忽略大小写) +func StrIsIn(s string, list []string) bool { + s = StrToLower(s) + for _, v := range list { + if StrToLower(v) == s { + return true + } + } + return false +} + +// StrJoin 拼接切片为字符串,指定分隔符 +func StrJoin(list []string, sep string) string { + return strings.Join(list, sep) +} + +// ---------------------- 随机数/随机字符串 ---------------------- +// 生成随机数、随机字符串(用于生成验证码、随机密码、唯一标识等) +// RandInt 生成[min, max]范围内的随机整数,失败返回0和错误 +func RandInt(min, max int) (int, error) { + if min > max { + return 0, errors.New("min is greater than max") + } + // 基于crypto/rand生成安全随机数(比math/rand更安全,适合生产环境) + num, err := rand.Int(rand.Reader, big.NewInt(int64(max-min+1))) + if err != nil { + return 0, err + } + return min + int(num.Int64()), nil +} + +// RandStr 生成指定长度的随机字符串(数字+大小写字母),失败返回""和错误 +func RandStr(length int) (string, error) { + if length <= 0 { + return "", errors.New("length must be greater than 0") + } + // 随机字符串源(可根据需求添加/移除字符,如去掉大写字母) + chars := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + charsLen := big.NewInt(int64(len(chars))) + result := make([]byte, length) + for i := 0; i < length; i++ { + // 逐个生成随机字符索引 + idx, err := rand.Int(rand.Reader, charsLen) + if err != nil { + return "", err + } + result[i] = chars[idx.Int64()] + } + return string(result), nil +} + +// RandNumStr 生成指定长度的纯数字随机字符串,失败返回""和错误 +func RandNumStr(length int) (string, error) { + if length <= 0 { + return "", errors.New("length must be greater than 0") + } + nums := "0123456789" + numsLen := big.NewInt(int64(len(nums))) + result := make([]byte, length) + for i := 0; i < length; i++ { + idx, err := rand.Int(rand.Reader, numsLen) + if err != nil { + return "", err + } + result[i] = nums[idx.Int64()] + } + return string(result), nil +} + +// ---------------------- 其他通用工具 ---------------------- +// GetCurrentDir 获取当前程序运行目录(适配Docker容器化,避免路径问题) +func GetCurrentDir() (string, error) { + dir, err := os.Getwd() + if err != nil { + return "", fmt.Errorf("get current dir failed: %w", err) + } + return dir, nil +} + +// MkdirIfNotExist 目录不存在则创建(支持多级目录),适配日志/文件存储 +func MkdirIfNotExist(path string) error { + if _, err := os.Stat(path); os.IsNotExist(err) { + // 0755:所有者读写执行,其他用户读执行,符合Linux/Docker权限规范 + if err := os.MkdirAll(path, 0755); err != nil { + return fmt.Errorf("mkdir %s failed: %w", path, err) + } + } + return nil +} \ No newline at end of file