Files
bl/common/data/share/share.go
昔念 0016be7ad0 feat(common): 重构 share 包并添加缓存扫描功能
- 移除了 sessionManager 结构体和相关方法
- 新增 cacheStore 结构体的 Scan 方法,用于扫描匹配模式的键
- 新增 cacheStore 结构体的 MGet 方法,用于批量获取多个键的值
- 优化了代码结构,提高了缓存操作的灵活性和效率
2025-08-09 22:29:41 +08:00

158 lines
4.7 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.

package share
import (
"context"
"fmt"
"regexp"
"strings"
"time"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/util/gconv"
)
var ShareManager = newSessionManager()
var (
// ErrCacheMiss 表示缓存未命中
ErrCacheMiss = gerror.New("缓存未找到")
// ErrTypeConvert 表示类型转换失败
ErrTypeConvert = gerror.New("缓存值类型转换失败")
)
// cacheStore 泛型缓存存储
type cacheStore[T any] struct {
manager *gcache.Cache // 缓存管理器
prefix string // 缓存键前缀
}
// 生成带前缀的缓存键
func (s *cacheStore[T]) formatKey(key string) string {
return s.prefix + strings.TrimSpace(key)
}
// Get 通过键获取缓存值
func (s *cacheStore[T]) Get(ctx context.Context, key string) (T, error) {
var zero T
result, err := s.manager.Get(ctx, s.formatKey(key))
if err != nil {
return zero, gerror.Wrapf(err, "获取缓存失败,键: %s", key)
}
if result.IsEmpty() {
return zero, ErrCacheMiss
}
// 使用 ConvertWithRefer 进行类型转换
value := gconv.ConvertWithRefer(result.Val(), zero)
// 类型断言检查转换结果
converted, ok := value.(T)
if !ok {
return zero, gerror.Wrapf(
ErrTypeConvert,
"键: %s缓存值实际类型: %T期望类型: %T",
key, result.Val(), zero,
)
}
return converted, nil
}
// Set 设置缓存值并带有效期
func (s *cacheStore[T]) Set(ctx context.Context, key string, value T, duration time.Duration) error {
err := s.manager.Set(ctx, s.formatKey(key), value, duration)
if err != nil {
return gerror.Wrapf(err, "设置缓存失败,键: %s值: %v", key, value)
}
fmt.Printf("[INFO] 缓存操作 [%s] 键: %s 值: %v 有效期: %v\n",
s.prefix, key, value, duration)
return nil
}
// Del 删除缓存
func (s *cacheStore[T]) Del(ctx context.Context, key string) error {
_, err := s.manager.Remove(ctx, s.formatKey(key))
if err != nil {
return gerror.Wrapf(err, "删除缓存失败,键: %s", key)
}
fmt.Printf("[INFO] 删除缓存 [%s] 键: %s 成功\n", s.prefix, key)
return nil
}
// Contains 检查缓存是否存在
func (s *cacheStore[T]) Contains(ctx context.Context, key string) (bool, error) {
exists, err := s.manager.Contains(ctx, s.formatKey(key))
if err != nil {
return false, gerror.Wrapf(err, "检查缓存是否存在失败,键: %s", key)
}
return exists, nil
}
// GetOrSet 获取缓存值,如果不存在则设置默认值
func (s *cacheStore[T]) GetOrSet(ctx context.Context, key string, defaultValue T, duration time.Duration) (T, error) {
var zero T
result, err := s.manager.GetOrSet(ctx, s.formatKey(key), defaultValue, duration)
if err != nil {
return zero, gerror.Wrapf(err, "获取或设置缓存失败,键: %s", key)
}
// 类型转换
value := gconv.ConvertWithRefer(result.Val(), zero)
converted, ok := value.(T)
if !ok {
return zero, gerror.Wrapf(
ErrTypeConvert,
"键: %s缓存值实际类型: %T期望类型: %T",
key, result.Val(), zero,
)
}
return converted, nil
}
// Scan 扫描匹配模式的键(先获取所有键,再内存筛选)
func (s *cacheStore[T]) Scan(ctx context.Context, pattern string) ([]string, error) {
// 1. 获取所有键
allKeys, err := s.manager.Keys(ctx)
if err != nil {
return nil, gerror.Wrapf(err, "获取所有键失败")
}
// 2. 筛选符合模式的键(使用字符串匹配,支持简单通配符*
var matchedKeys []string
for _, key := range allKeys {
// 简单模式匹配:支持*匹配任意字符可根据需求扩展为glob匹配
if matchSimplePattern(key.(string), pattern) {
matchedKeys = append(matchedKeys, key.(string))
}
}
return matchedKeys, nil
}
// 简单模式匹配(支持*通配符)
func matchSimplePattern(str, pattern string) bool {
// 替换pattern中的*为正则匹配符,转义其他特殊字符
regexPattern := strings.ReplaceAll(regexp.QuoteMeta(pattern), "\\*", ".*")
regexPattern = "^" + regexPattern + "$" // 全匹配
matched, _ := regexp.MatchString(regexPattern, str)
return matched
}
// MGet 批量获取多个键的值循环调用Get实现
func (s *cacheStore[T]) MGet(ctx context.Context, keys []string) ([]interface{}, error) {
values := make([]interface{}, len(keys))
for i, key := range keys {
formattedKey := s.formatKey(key) // 格式化键(添加前缀)
result, err := s.manager.Get(ctx, formattedKey)
if err != nil {
return nil, gerror.Wrapf(err, "批量获取缓存失败,键: %s", key)
}
if result.IsEmpty() {
values[i] = nil // 未命中时存nil
} else {
values[i] = result.Val()
}
}
return values, nil
}