本节内容,我们将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啦 ~


