Files
dygou_go/internal/utils/utils.go
T
yml2213 3ae9cb4a42 重构: 活动热切换并发安全 + 代码清理优化
- 活动切换并发安全:App/Scheduler 增加 client/cfg 读写锁与快照访问,
  支持运行中热替换客户端,切换活动不再静默覆盖用户自定义 timeApiUrl
- 启动失败时写入崩溃日志文件便于事后排查
- 前端类型声明从 Wails 自动生成的绑定派生,避免手写契约漂移
- 提取 parseAccountFile 消除 ExportAccounts/OrganizeAccounts 重复解析逻辑
- 删除 utils 中未使用的 ReadJSON/WriteJSON/WriteError 及空目录 internal/app
- gofmt 统一格式化(activity/types/scheduler 字段对齐)
- 新增 logger/seckill/utils 单元测试
- 清理 git 中遗留产物(frontend/app.js、yml.txt、其他日志/)并补全 .gitignore
2026-07-29 12:33:16 +08:00

117 lines
2.8 KiB
Go

package utils
import (
"fmt"
"strconv"
"strings"
"time"
)
// AppendCacheBuster 给 URL 追加时间戳,避免时间接口被缓存。
func AppendCacheBuster(rawURL string) string {
sep := "?"
if strings.Contains(rawURL, "?") {
sep = "&"
}
return rawURL + sep + "_=" + strconv.FormatInt(time.Now().UnixNano(), 10)
}
// CloneStringMap 复制 map,避免异步任务读到调用方后续修改。
func CloneStringMap(in map[string]string) map[string]string {
out := make(map[string]string, len(in))
for k, v := range in {
out[k] = v
}
return out
}
// MergeCookie 把指定 Cookie 写入原 Cookie 字符串,已有同名 Cookie 会被覆盖。
func MergeCookie(cookie, name, value string) string {
parts := strings.Split(cookie, ";")
pairs := make([]string, 0, len(parts)+1)
replaced := false
for _, part := range parts {
part = strings.TrimSpace(part)
if part == "" {
continue
}
key, _, ok := strings.Cut(part, "=")
if ok && strings.TrimSpace(key) == name {
pairs = append(pairs, name+"="+value)
replaced = true
continue
}
pairs = append(pairs, part)
}
if !replaced && value != "" {
pairs = append(pairs, name+"="+value)
}
return strings.Join(pairs, "; ")
}
// TrimForLog 截断接口响应,避免日志刷屏。
func TrimForLog(s string, max int) string {
s = strings.TrimSpace(s)
if len(s) <= max {
return s
}
return s[:max] + "..."
}
// EmptyDefault 在字符串为空时返回默认值。
func EmptyDefault(value, fallback string) string {
if strings.TrimSpace(value) == "" {
return fallback
}
return value
}
// SafeFilename 替换文件名中的危险字符。
func SafeFilename(name string) string {
replacer := strings.NewReplacer("/", "_", "\\", "_", ":", "_", "*", "_", "?", "_", "\"", "_", "<", "_", ">", "_", "|", "_")
return replacer.Replace(name)
}
// MaskCookie 返回 Cookie 摘要,避免把完整凭据暴露给前端。
func MaskCookie(cookie string) string {
pairs := strings.Split(cookie, ";")
masked := make([]string, 0, 3)
total := 0
for _, pair := range pairs {
key, value, ok := strings.Cut(strings.TrimSpace(pair), "=")
if !ok || key == "" {
continue
}
total++
if len(masked) >= 3 {
continue
}
masked = append(masked, key+"="+MaskValue(value))
}
if total == 0 {
return ""
}
if total > len(masked) {
masked = append(masked, fmt.Sprintf("...共%d项", total))
}
return strings.Join(masked, "; ")
}
// MaskValue 保留少量首尾字符用于识别,其余替换为星号。
func MaskValue(value string) string {
value = strings.TrimSpace(value)
if value == "" {
return "****"
}
runes := []rune(value)
if len(runes) <= 8 {
return "****"
}
return string(runes[:4]) + "****" + string(runes[len(runes)-4:])
}
// RoundDuration 将时间四舍五入到毫秒。
func RoundDuration(d time.Duration) time.Duration {
return d.Round(time.Millisecond)
}