Przeglądaj źródła

feat: cache 包

runningwater 5 miesięcy temu
rodzic
commit
6d9ec7b5aa

+ 23 - 0
bootstrap/cache.go

@@ -0,0 +1,23 @@
+// Author: simon (ynwdlxm@163.com)
+// Date: 2025/7/21 12:42
+// Desc:
+
+package bootstrap
+
+import (
+	"fmt"
+
+	"github.com/runningwater/gohub/pkg/cache"
+	"github.com/runningwater/gohub/pkg/config"
+)
+
+func SetupCache() {
+	// 初始化缓存的专用 redis client
+	rds := cache.NewRedisStore(
+		fmt.Sprintf("%v:%v", config.GetString("redis.host"), config.GetString("redis.port")),
+		config.GetString("redis.username"),
+		config.GetString("redis.password"),
+		config.GetInt("redis.database_cache"),
+	)
+	cache.InitWithCacheStore(rds)
+}

+ 2 - 0
config/redis.go

@@ -12,6 +12,8 @@ func init() {
 
 			// 业务类型存储使用 1(图片验证码、短信验证码、会话)
 			"database": config.Env("REDIS_DATABASE", 1),
+			// 缓存 cache 包使用 0, 缓存清空应不影响业务
+			"database_cache": config.Env("REDIS_CACHE_DB", 0),
 		}
 	})
 }

+ 3 - 0
main.go

@@ -41,6 +41,9 @@ func main() {
 
 			// 初始化 Redis
 			bootstrap.SetupRedis()
+
+			// 初始化 Cache
+			bootstrap.SetupCache()
 		},
 	}
 

+ 61 - 0
pkg/cache/RedisStore.go

@@ -0,0 +1,61 @@
+// Author: simon (ynwdlxm@163.com)
+// Date: 2025/7/21 09:56
+// Desc: redis 缓存,实现 Store 接口
+
+package cache
+
+import (
+	"time"
+
+	"github.com/runningwater/gohub/pkg/config"
+	"github.com/runningwater/gohub/pkg/redis"
+)
+
+type RedisStore struct {
+	RedisClient *redis.Client
+	KeyPrefix   string
+}
+
+func NewRedisStore(address, username, password string, db int) *RedisStore {
+	rs := &RedisStore{
+		RedisClient: redis.NewClient(address, username, password, db),
+		KeyPrefix:   config.GetString("app.name") + ":cache:",
+	}
+	return rs
+}
+
+func (r *RedisStore) Set(key, value string, expire time.Duration) {
+	r.RedisClient.Set(r.KeyPrefix+key, value, expire)
+}
+
+func (r *RedisStore) Get(key string) string {
+	return r.RedisClient.Get(r.KeyPrefix + key)
+}
+
+func (r *RedisStore) Has(key string) bool {
+	return r.RedisClient.Has(r.KeyPrefix + key)
+}
+
+func (r *RedisStore) Forget(key string) {
+	r.RedisClient.Del(r.KeyPrefix + key)
+}
+
+func (r *RedisStore) Forever(key, value string) {
+	r.RedisClient.Set(r.KeyPrefix+key, value, 0)
+}
+
+func (r *RedisStore) Flush() {
+	r.RedisClient.FlushDb()
+}
+
+func (r *RedisStore) IsAlive() error {
+	return r.RedisClient.Ping()
+}
+
+func (r *RedisStore) Increment(params ...any) {
+	r.RedisClient.Increment(params)
+}
+
+func (r *RedisStore) Decrement(params ...any) {
+	r.RedisClient.Decrement(params)
+}

+ 152 - 0
pkg/cache/cache.go

@@ -0,0 +1,152 @@
+// Author: simon (ynwdlxm@163.com)
+// Date: 2025/7/21 10:10
+// Desc: 缓存包
+
+package cache
+
+import (
+	"encoding/json"
+	"sync"
+	"time"
+
+	"github.com/spf13/cast"
+
+	"github.com/runningwater/gohub/pkg/logger"
+)
+
+type Service struct {
+	Store Store
+}
+
+var once sync.Once
+var Cache *Service
+
+func InitWithCacheStore(store Store) {
+	once.Do(func() {
+		Cache = &Service{
+			Store: store,
+		}
+	})
+}
+
+func Set(key string, value any, expire time.Duration) {
+	bytes, err := json.Marshal(value)
+	logger.LogIf(err)
+	Cache.Store.Set(key, string(bytes), expire)
+}
+
+func Get(key string) any {
+	stringValue := Cache.Store.Get(key)
+	var wanted any
+	err := json.Unmarshal([]byte(stringValue), &wanted)
+	logger.LogIf(err)
+	return wanted
+}
+
+func Has(key string) bool {
+	return Cache.Store.Has(key)
+}
+
+// GetObject 获取对象,用法如下:
+//
+//	model := user.User{}
+//	cache.GetObject("user:1", &model)
+func GetObject(key string, wanted any) {
+	val := Cache.Store.Get(key)
+	if len(val) > 0 {
+		err := json.Unmarshal([]byte(val), &wanted)
+		logger.LogIf(err)
+	} else {
+		logger.WarnString("cache", "GetObject", "cache key ["+key+"] not found")
+	}
+}
+
+func GetString(key string) string {
+	return cast.ToString(Get(key))
+}
+
+func GetBool(key string) bool {
+	return cast.ToBool(Get(key))
+}
+
+func GetInt(key string) int {
+	return cast.ToInt(Get(key))
+}
+
+func GetInt32(key string) int32 {
+	return cast.ToInt32(Get(key))
+}
+
+func GetInt64(key string) int64 {
+	return cast.ToInt64(Get(key))
+}
+
+func GetUint(key string) uint {
+	return cast.ToUint(Get(key))
+}
+
+func GetUint32(key string) uint32 {
+	return cast.ToUint32(Get(key))
+}
+
+func GetUint64(key string) uint64 {
+	return cast.ToUint64(Get(key))
+}
+
+func GetFloat32(key string) float32 {
+	return cast.ToFloat32(Get(key))
+}
+
+func GetFloat64(key string) float64 {
+	return cast.ToFloat64(Get(key))
+}
+
+func GetTime(key string) time.Time {
+	return cast.ToTime(Get(key))
+}
+
+func GetDuration(key string) time.Duration {
+	return cast.ToDuration(Get(key))
+}
+func GetIntSlice(key string) []int {
+	return cast.ToIntSlice(Get(key))
+}
+func GetStringSlice(key string) []string {
+	return cast.ToStringSlice(Get(key))
+}
+func GetStringMap(key string) map[string]string {
+	return cast.ToStringMapString(Get(key))
+}
+func GetStringMapString(key string) map[string]string {
+	return cast.ToStringMapString(Get(key))
+}
+func GetStringMapStringSlice(key string) map[string][]string {
+	return cast.ToStringMapStringSlice(Get(key))
+}
+func GetStringMapInt(key string) map[string]int {
+	return cast.ToStringMapInt(Get(key))
+}
+
+func Forget(key string) {
+	Cache.Store.Forget(key)
+}
+
+func Forever(key string, value string) {
+	Cache.Store.Set(key, value, 0)
+}
+
+func Flush() {
+	Cache.Store.Flush()
+}
+
+func Increment(params ...any) {
+	Cache.Store.Increment(params...)
+}
+
+func Decrement(params ...any) {
+	Cache.Store.Decrement(params...)
+}
+
+func IsAlive() error {
+	return Cache.Store.IsAlive()
+}

+ 23 - 0
pkg/cache/store_interface.go

@@ -0,0 +1,23 @@
+// Package cache 系统缓存包
+package cache
+
+import (
+	"time"
+)
+
+type Store interface {
+	Set(key, value string, expire time.Duration)
+	Get(key string) string
+	Has(key string) bool
+	Forget(key string)
+	Forever(key, value string)
+	Flush()
+
+	IsAlive() error
+
+	// Increment 自增
+	//  当参数只有1个时,为key 增加1
+	//  当参数有2个时,为key 增加值
+	Increment(params ...any)
+	Decrement(params ...any)
+}

+ 1 - 1
pkg/captcha/store_redis.go

@@ -12,7 +12,7 @@ import (
 // RedisStore is a store for captcha using Redis.
 // It implements the Save interface. base64Captcha.Store interface.
 type RedisStore struct {
-	RedisClient *redis.RedisClient
+	RedisClient *redis.Client
 	KeyPrefix   string
 }
 

+ 1 - 1
pkg/logger/logger.go

@@ -1,4 +1,4 @@
-// Pacage logger provides a simple wrapper around zap logger
+// Package logger provides a simple wrapper around zap logger
 package logger
 
 import (

+ 17 - 15
pkg/redis/redis.go

@@ -3,29 +3,31 @@ package redis
 
 import (
 	"context"
+	"errors"
 	"sync"
 	"time"
 
 	"github.com/redis/go-redis/v9"
+
 	"github.com/runningwater/gohub/pkg/logger"
 )
 
-// RedisClient Redis 服务
-type RedisClient struct {
+// Client Redis 服务
+type Client struct {
 	Client  *redis.Client
 	Context context.Context
 }
 
 // Ping 测试 Redis 连接
 // 通过 Ping 方法测试 Redis 连接是否正常
-func (rds *RedisClient) Ping() error {
+func (rds *Client) Ping() error {
 	_, err := rds.Client.Ping(rds.Context).Result()
 	return err
 }
 
 // Set 设置 Redis 键值对, 并设置过期时间
-func (rds *RedisClient) Set(key string, value any, expiraction time.Duration) bool {
-	if err := rds.Client.Set(rds.Context, key, value, expiraction).Err(); err != nil {
+func (rds *Client) Set(key string, value any, expiration time.Duration) bool {
+	if err := rds.Client.Set(rds.Context, key, value, expiration).Err(); err != nil {
 		logger.ErrorString("Redis", "Set", err.Error())
 		return false
 	}
@@ -33,7 +35,7 @@ func (rds *RedisClient) Set(key string, value any, expiraction time.Duration) bo
 }
 
 // Get 获取 Redis 键值对
-func (rds *RedisClient) Get(key string) string {
+func (rds *Client) Get(key string) string {
 	val, err := rds.Client.Get(rds.Context, key).Result()
 	if err != nil {
 		logger.ErrorString("Redis", "Get", err.Error())
@@ -43,10 +45,10 @@ func (rds *RedisClient) Get(key string) string {
 }
 
 // Has 检查 Redis 中是否存在某个键
-func (rds *RedisClient) Has(key string) bool {
+func (rds *Client) Has(key string) bool {
 	_, err := rds.Client.Get(rds.Context, key).Result()
 	if err != nil {
-		if err == redis.Nil {
+		if errors.Is(err, redis.Nil) {
 			logger.ErrorString("Redis", "Has", err.Error())
 		}
 		return false
@@ -55,7 +57,7 @@ func (rds *RedisClient) Has(key string) bool {
 }
 
 // Del 删除 Redis 中的键, 支持多个 key 传参
-func (rds *RedisClient) Del(keys ...string) bool {
+func (rds *Client) Del(keys ...string) bool {
 	if err := rds.Client.Del(rds.Context, keys...).Err(); err != nil {
 		logger.ErrorString("Redis", "Del", err.Error())
 		return false
@@ -64,7 +66,7 @@ func (rds *RedisClient) Del(keys ...string) bool {
 }
 
 // FlushDb 清空 Redis 数据库
-func (rds *RedisClient) FlushDb() bool {
+func (rds *Client) FlushDb() bool {
 	if err := rds.Client.FlushDB(rds.Context).Err(); err != nil {
 		logger.ErrorString("Redis", "FlushDb", err.Error())
 		return false
@@ -74,7 +76,7 @@ func (rds *RedisClient) FlushDb() bool {
 
 // Increment 当参数只有 1 个时,增加 Redis 中的键值对增加 1
 // 当参数有 2 个时,第一个参数为 Key,第二个参数为增加的值 int64 类型
-func (rds *RedisClient) Increment(args ...any) bool {
+func (rds *Client) Increment(args ...any) bool {
 	switch len(args) {
 	case 1:
 		key := args[0].(string)
@@ -98,7 +100,7 @@ func (rds *RedisClient) Increment(args ...any) bool {
 
 // Decrement 当参数只有 1 个时,减少 Redis 中的键值对减少 1
 // 当参数有 2 个时,第一个参数为 Key,第二个参数为减少的值 int64 类型
-func (rds *RedisClient) Decrement(args ...any) bool {
+func (rds *Client) Decrement(args ...any) bool {
 	switch len(args) {
 	case 1:
 		key := args[0].(string)
@@ -151,7 +153,7 @@ func (rds *RedisClient) Decrement(args ...any) bool {
 var once sync.Once
 
 // Redis 全局 Redis, 使用 db 1
-var Redis *RedisClient
+var Redis *Client
 
 // ConnectRedis 连接 redis 数据库,设置全局 Redis 对象
 func ConnectRedis(address, username, password string, db int) {
@@ -160,9 +162,9 @@ func ConnectRedis(address, username, password string, db int) {
 	})
 }
 
-func NewClient(address, username, password string, db int) *RedisClient {
+func NewClient(address, username, password string, db int) *Client {
 
-	rds := &RedisClient{}
+	rds := &Client{}
 	rds.Context = context.Background()
 
 	// 使用 redis 库里的 NewClient 初始化连接

+ 1 - 1
pkg/verifycode/store_reids.go

@@ -12,7 +12,7 @@ import (
 // 验证码存储在 Redis 中
 // 键名格式为:keyPrefix:code
 type RedisStore struct {
-	RedisClient *redis.RedisClient
+	RedisClient *redis.Client
 	KeyPrefix   string
 }