本节内容,我们将redis引入我们的框架 (本地redis部署可参考 Redis Cluster集群部署 无需搭建集群,部署单redis即可)。
第一步 引入redis服务 – go-redis
go get github.com/go-redis/redis/v8
第二步 对go-redis进行封装
mkdir ./library/cache
创建文件./library/cache/redis.go:
package cache import ( "github.com/gin-gonic/gin" "github.com/go-redis/redis/v8" "time" ) type RedisClient struct { Client *redis.Client Ctx *gin.Context } type RedisConf struct { Addr string `yaml:"addr"` Password string `yaml:"password"` PoolSize int `yaml:"poolSize"` DialTimeout time.Duration `yaml:"dialTimeout"` ReadTimeout time.Duration `yaml:"readTimeout"` WriteTimeout time.Duration `yaml:"writeTimeout"` } var RedisCacheClient *RedisClient func InitRedisClient(ctx *gin.Context, redisConf *RedisConf) { RedisCacheClient = &RedisClient{Client: redis.NewClient(&redis.Options{ Addr: redisConf.Addr, Password: redisConf.Password, PoolSize: redisConf.PoolSize, DialTimeout: redisConf.DialTimeout, ReadTimeout: redisConf.ReadTimeout, WriteTimeout: redisConf.WriteTimeout, }), Ctx: ctx} } func GetRedisClient() *RedisClient { return RedisCacheClient } func (r RedisClient) Set(key string, value interface{}, expiration time.Duration) error { return r.Client.Set(r.Ctx, key, value, expiration).Err() } func (r RedisClient) Get(key string) (string, error) { return r.Client.Get(r.Ctx, key).Result() } func (r RedisClient) Del(key string) error { return r.Client.Del(r.Ctx, key).Err() } func (r RedisClient) SetNX(key string, value interface{}, expiration time.Duration) error { return r.Client.SetNX(r.Ctx, key, value, expiration).Err() } func (r RedisClient) Expire(key string, expiration time.Duration) error { return r.Client.Expire(r.Ctx, key, expiration).Err() } func (r RedisClient) Exists(key string) error { return r.Client.Exists(r.Ctx, key).Err() } func (r RedisClient) HSet(key string, values ...interface{}) error { return r.Client.HSet(r.Ctx, key, values ...).Err() } func (r RedisClient) HGet(key, field string) (string, error) { return r.Client.HGet(r.Ctx, key, field).Result() } func (r RedisClient) MSet(values ...interface{}) error { return r.Client.MSet(r.Ctx, values ...).Err() } func (r RedisClient) MGet(keys ...string) ([]interface{}, error) { return r.Client.MGet(r.Ctx, keys ...).Result() } func (r RedisClient) HSetNX(key, field string, value interface{}) error { return r.Client.HSetNX(r.Ctx, key, field, value).Err() } func (r RedisClient) HExists(key, field string) error { return r.Client.HExists(r.Ctx, key, field).Err() } func (r RedisClient) HDel(key, field string) error { return r.Client.HDel(r.Ctx, key, field).Err() } func (r RedisClient) HMSet(key string, values ...interface{}) error { return r.Client.HMSet(r.Ctx, key, values ...).Err() } func (r RedisClient) HMGet(key string, fields ...string) ([]interface{}, error) { return r.Client.HMGet(r.Ctx, key, fields ...).Result() } func (r RedisClient) IncrBy(key string, value int64) error { return r.Client.IncrBy(r.Ctx, key, value).Err() } func (r RedisClient) DecrBy(key string, value int64) error { return r.Client.DecrBy(r.Ctx, key, value).Err() } func (r RedisClient) SAdd(key string, members ...interface{}) error { return r.Client.SAdd(r.Ctx, key, members ...).Err() } func (r RedisClient) ZRange(key string, start, stop int64) ([]string, error) { return r.Client.ZRange(r.Ctx, key, start, stop).Result() } func (r RedisClient) ZRangeByScore(key string, opt *redis.ZRangeBy) ([]string, error) { return r.Client.ZRangeByScore(r.Ctx, key, opt).Result() } func (r RedisClient) ZRangeByScoreWithScores(key string, opt *redis.ZRangeBy) ([]redis.Z, error) { return r.Client.ZRangeByScoreWithScores(r.Ctx, key, opt).Result() } func (r RedisClient) ZRevRange(key string, start, stop int64) ([]string, error) { return r.Client.ZRevRange(r.Ctx, key, start, stop).Result() } func (r RedisClient) ZRevRangeByScore(key string, opt *redis.ZRangeBy) ([]string, error) { return r.Client.ZRevRangeByScore(r.Ctx, key, opt).Result() } func (r RedisClient) ZRevRangeByScoreWithScores(key string, opt *redis.ZRangeBy) ([]redis.Z, error) { return r.Client.ZRevRangeByScoreWithScores(r.Ctx, key, opt).Result() } func (r RedisClient) ZCard(key string) (int64, error) { return r.Client.ZCard(r.Ctx, key).Result() } func (r RedisClient) SIsMember(key string, member interface{}) (bool, error) { return r.Client.SIsMember(r.Ctx, key, member).Result() } func (r RedisClient) LPush(key string, values ...interface{}) error { return r.Client.LPush(r.Ctx, key, values ...).Err() } func (r RedisClient) RPop(key string) (string, error) { return r.Client.RPop(r.Ctx, key).Result() } func (r RedisClient) RPush(key string, values ...interface{}) error { return r.Client.LPush(r.Ctx, key, values ...).Err() } func (r RedisClient) LPop(key string) (string, error) { return r.Client.RPop(r.Ctx, key).Result() } func (r RedisClient) LRange(key string, start, stop int64) error { return r.Client.LRange(r.Ctx, key, start, stop).Err() }
该文件封装了一些常用的redis方法,便于直接使用
第三步 增加redis配置与读取
./conf/config.yaml, 新增
log: # 日志配置 # 日志路径 dir: "./log" redis: addr: 10.252.187.163:6379 password: "123456" # 连接池大小 poolSize: 10 # 连接超时时间 dialTimeout: 100ms # 读超时时间 readTimeout: 500ms # 写超时时间 writeTimeout: 300ms
./conf/config.go
package conf import ( "fusheng-admin/library/cache" "gopkg.in/yaml.v3" "io/ioutil" ) var BaseConf Config var ConfigFile = "./conf/config.yaml" type LogConf struct { Dir string `yaml:"dir"` } type Config struct { Log LogConf `yaml:"log"` Redis *cache.RedisConf `yaml:"redis"` } func InitConf() { if yamlFile, err := ioutil.ReadFile(ConfigFile); err != nil { panic("read conf error: " + err.Error()) } else if err = yaml.Unmarshal(yamlFile, &BaseConf); err != nil { panic("conf file unmarshal error: " + err.Error()) } }
第四步 redis初始化
创建./helpers目录,存放一些辅助工具函数
./helpers
创建文件./helpers/redis.go:
package helpers import ( "fusheng-admin/conf" "fusheng-admin/library/cache" "github.com/gin-gonic/gin" ) func InitRedis() { redisConf := conf.BaseConf.Redis cache.InitRedisClient(&gin.Context{}, redisConf) }
第五步 main函数中调用
./main.go :
package main import ( "fusheng-admin/conf" "fusheng-admin/helpers" "fusheng-admin/library/middleware" "fusheng-admin/router" "github.com/gin-gonic/gin" ) func main() { // 1.创建路由 r := gin.Default() r.Use(middleware.LoggerToFile()) // 初始化配置 conf.InitConf() helpers.InitRedis() // 2.绑定路由规则,执行的函数 // gin.Context,封装了request和response router.Http(r) // 3.监听端口,默认在8080 // Run("里面不指定端口号默认为8088") r.Run(":8088") }
第六步 测试
创建测试目录 ./test
创建初始化测试工具 ./test/test_init.go:
package test import ( "fusheng-admin/conf" "fusheng-admin/helpers" ) func init() { conf.ConfigFile = "../conf/config.yaml" // 初始化配置 conf.InitConf() helpers.InitRedis() }
创建redis测试 ./test/redis_test.go:
package test import ( "fmt" "fusheng-admin/library/cache" "testing" "time" ) func TestRedis(t *testing.T) { text := "上次请求时间为: " lastReqKey := "test:last:req:time" redisClient := cache.GetRedisClient() val, err := redisClient.Get(lastReqKey) if err != nil { t.Log(fmt.Sprintf("get from redis error. %#v", err.Error())) } text += val err = redisClient.Set(lastReqKey, time.Now().Unix(), 600 * time.Second) if err != nil { t.Log(fmt.Sprintf("set redis error. %#v", err.Error())) } t.Log(text) }
执行测试(根目录下执行):
go test -v test/test_init.go test/redis_test.go
第一次执行:
第二次执行:
测试无误,至此,我们的项目已经支持redis啦 ~