从零开始搭建go项目(gin框架)(四) – 支持Redis

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

附录

https://github.com/go-redis/redis

3 评论
最新
最旧 最多投票
内联反馈
查看所有评论
滚动至顶部