Files
trading_assistant/trading_assistant_api/common/utils/common.go
2026-02-06 16:51:09 +08:00

276 lines
8.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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:05Go诞生时间固定模板
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
}