runningwater пре 8 месеци
родитељ
комит
237543f463
4 измењених фајлова са 193 додато и 2 уклоњено
  1. 20 0
      bootstrap/redis.go
  2. 17 0
      config/redis.go
  3. 4 2
      main.go
  4. 152 0
      pkg/redis/redis.go

+ 20 - 0
bootstrap/redis.go

@@ -0,0 +1,20 @@
+package bootstrap
+
+import (
+	"fmt"
+
+	"github.com/runningwater/gohub/pkg/config"
+	"github.com/runningwater/gohub/pkg/redis"
+)
+
+// SetupRedis 初始化 Redis
+func SetupRedis() {
+
+	// 连接 Redis
+	redis.ConnectRedis(
+		fmt.Sprintf("%s:%s", config.Get("redis.host"), config.Get("redis.port")),
+		"", // redis.username 为空
+		config.GetString("redis.password"),
+		config.GetInt("redis.database"),
+	)
+}

+ 17 - 0
config/redis.go

@@ -0,0 +1,17 @@
+package config
+
+import "github.com/runningwater/gohub/pkg/config"
+
+func init() {
+	config.Add("redis", func() map[string]any {
+		return map[string]any{
+			// Redis 连接配置
+			"host":     config.Env("REDIS_HOST", "127.0.0.1"),
+			"port":     config.Env("REDIS_PORT", "6379"),
+			"password": config.Env("REDIS_PASSWORD", ""),
+
+			// 业务类型存储使用 1(图片验证码、短信验证码、会话)
+			"database": config.Env("REDIS_DATABASE", 1),
+		}
+	})
+}

+ 4 - 2
main.go

@@ -29,12 +29,14 @@ func main() {
 	// 注意: 初始化 DB 前应该先初始化 logger
 	bootstrap.SetupDB()
 
+	// 初始化 Redis
+	bootstrap.SetupRedis()
 
 	// gin 框架设置为发布模式,线上环境需要设置
 	gin.SetMode(gin.ReleaseMode)
 
 	// Gin 框架初始化
-	r:= gin.New()
+	r := gin.New()
 
 	// 初始化路由绑定
 	bootstrap.SetupRoute(r)
@@ -43,4 +45,4 @@ func main() {
 	if err != nil {
 		fmt.Println("启动失败", err.Error())
 	}
-}
+}

+ 152 - 0
pkg/redis/redis.go

@@ -0,0 +1,152 @@
+// Package redis 工具包
+package redis
+
+import (
+	"context"
+	"sync"
+	"time"
+
+	"github.com/go-redis/redis"
+	"github.com/runningwater/gohub/pkg/logger"
+)
+
+// RedisClient Redis 服务
+type RedisClient struct {
+	Client  *redis.Client
+	Context context.Context
+}
+
+// Ping 测试 Redis 连接
+// 通过 Ping 方法测试 Redis 连接是否正常
+func (rds *RedisClient) Ping() error {
+	_, err := rds.Client.Ping().Result()
+	return err
+}
+
+// Set 设置 Redis 键值对, 并设置过期时间
+func (rds *RedisClient) Set(key string, value any, expiraction time.Duration) bool {
+	if err := rds.Client.Set(key, value, expiraction).Err(); err != nil {
+		logger.ErrorString("Redis", "Set", err.Error())
+		return false
+	}
+	return true
+}
+
+// Get 获取 Redis 键值对
+func (rds *RedisClient) Get(key string) string {
+	val, err := rds.Client.Get(key).Result()
+	if err != nil {
+		logger.ErrorString("Redis", "Get", err.Error())
+		return ""
+	}
+	return val
+}
+
+// Has 检查 Redis 中是否存在某个键
+func (rds *RedisClient) Has(key string) bool {
+	_, err := rds.Client.Get(key).Result()
+	if err != nil {
+		if err == redis.Nil {
+			logger.ErrorString("Redis", "Has", err.Error())
+		}
+		return false
+	}
+	return true
+}
+
+// Del 删除 Redis 中的键, 支持多个 key 传参
+func (rds *RedisClient) Del(keys ...string) bool {
+	if err := rds.Client.Del(keys...).Err(); err != nil {
+		logger.ErrorString("Redis", "Del", err.Error())
+		return false
+	}
+	return true
+}
+
+// FlushDb 清空 Redis 数据库
+func (rds *RedisClient) FlushDb() bool {
+	if err := rds.Client.FlushDB().Err(); err != nil {
+		logger.ErrorString("Redis", "FlushDb", err.Error())
+		return false
+	}
+	return true
+}
+
+// Increment 当参数只有 1 个时,增加 Redis 中的键值对增加 1
+// 当参数有 2 个时,第一个参数为 Key,第二个参数为增加的值 int64 类型
+func (rds *RedisClient) Increment(args ...any) bool {
+	switch len(args) {
+	case 1:
+		key := args[0].(string)
+		if err := rds.Client.Incr(key).Err(); err != nil {
+			logger.ErrorString("Redis", "Increment", err.Error())
+			return false
+		}
+	case 2:
+		key := args[0].(string)
+		value := args[1].(int64)
+		if err := rds.Client.IncrBy(key, value).Err(); err != nil {
+			logger.ErrorString("Redis", "Increment", err.Error())
+			return false
+		}
+	default:
+		logger.ErrorString("Redis", "Increment", "参数错误, 只能传入 1 或 2 个参数")
+		return false
+	}
+	return true
+}
+
+// Decrement 当参数只有 1 个时,减少 Redis 中的键值对减少 1
+// 当参数有 2 个时,第一个参数为 Key,第二个参数为减少的值 int64 类型
+func (rds *RedisClient) Decrement(args ...any) bool {
+	switch len(args) {
+	case 1:
+		key := args[0].(string)
+		if err := rds.Client.Decr(key).Err(); err != nil {
+			logger.ErrorString("Redis", "Decrement", err.Error())
+			return false
+		}
+	case 2:
+		key := args[0].(string)
+		value := args[1].(int64)
+		if err := rds.Client.DecrBy(key, value).Err(); err != nil {
+			logger.ErrorString("Redis", "Decrement", err.Error())
+			return false
+		}
+	default:
+		logger.ErrorString("Redis", "Decrement", "参数错误, 只能传入 1 或 2 个参数")
+		return false
+	}
+	return true
+}
+
+// once 确保全局的 Redis 对象只实例一次
+var once sync.Once
+
+// Redis 全局 Redis, 使用 db 1
+var Redis *RedisClient
+
+// ConnectRedis 连接 redis 数据库,设置全局 Redis 对象
+func ConnectRedis(address, username, password string, db int) {
+	once.Do(func() {
+		Redis = NewClient(address, username, password, db)
+	})
+}
+
+func NewClient(address, username, password string, db int) *RedisClient {
+
+	rds := &RedisClient{}
+	rds.Context = context.Background()
+
+	// 使用 redis 库里的 NewClient 初始化连接
+	rds.Client = redis.NewClient(&redis.Options{
+		Addr:     address,
+		Password: password,
+		DB:       db,
+	})
+
+	err := rds.Ping()
+	logger.LogIf(err)
+
+	return rds
+}