网络知识 娱乐 Go语言Redis API基本功能实践

Go语言Redis API基本功能实践

本来想着放弃Go了,没想到人算不如天算,还是得继续Go的学习和练习。由于之前提到的原因,又要把Java版本操作Redis也要迁移到Go版本了。

学习路线如下:

  1. Redis连接和基本操作
  2. 集合操作:hash、list、set和有序集合
  3. Redis stream

在整个学习过程中也对比了一下Go和Java版本的Redis,也发现Go语言在使用上是非常简洁的,而且默认自带Redis连接池。

按照我的习惯,一般都会都原声的API进行封装,例如之前写到的Java版本Redis各类操作性能实践:FunTester框架Redis压测预备。

由于Go已经解决了连接池的问题,封装主要解决的就是默认返回值和异常处理。还没在实际的工作中应用,只能先按照我写Java的经验来谢啦。目前还在学习Go语言简易线程池的问题以及Java的其他问题,再叠加最近工作的确比较忙,所以最近学得少,写的也少了。后续写完Go的Redis教程以后,我会针对这些Redis的API进行性能测试实践分享。

依赖

Go的依赖相对简单,我使用的go.mod的方式,也可以通过将依赖下载到本地的path中。

github.com/go-redis/redis v6.15.9+incompatible

Redis API封装

这里发现Go版本的Redis库相比Java版本都了几个批量操作的API,都是以M开头的,可能是因为使用场景并不多,所以写Java封装方法的时候也没注意,改天找找Java jedis的API。

package redisnnimport (n "fmt"n "funtester/base"n "github.com/go-redis/redis"n "log"n "time"n)nn//redis.Options 默认池大小为10×cpu核数nntype RedisBase struct {n Host stringn db intn pool *redis.Clientn}nn// init 初始化类,创建连接池n// @Description:n//nfunc NewRdisPool(host string, db int) RedisBase {n redisBase := RedisBase{Host: host, db: db}n redisBase.pool = redis.NewClient(&redis.Options{n //Password: "",n Addr: host,n DB: 0,n MaxRetries: 3,n MinRetryBackoff: 100 * time.Millisecond,n DialTimeout: 5 * time.Second,n WriteTimeout: 1 * time.Second,n PoolSize: 200,n MaxConnAge: 10 * time.Second,n IdleTimeout: 8 * time.Second,n })n _, err := redisBase.pool.Ping().Result()n if err != nil {n log.Fatal("连接失败", err)n }n log.Println("Redis 连接成功")n ping := redisBase.Ping()n if ping == "PONG" {n log.Println("确认连接成功!")n }n return redisBasen}nnfunc (r RedisBase) Ping() string {n ping := r.pool.Ping()n result, err := ping.Result()n if err != nil {n log.Println("确认连接失败")n }n return resultn}nn// Keys 获取所有的服务条件的keys列表n// @Description:n// @param pattenn// @return []stringn//nfunc (r RedisBase) Keys(patten string) []string {n result, err := r.pool.Keys(patten).Result()n if err != nil {n log.Printf("获取keys: %s 失败%sn", patten, err.Error())n return niln }n return resultn}nn// Set 设置一个key的值n// @Description:n// @param keyn// @param valuen// @param expirationn// @return stringn//nfunc (r RedisBase) Set(key string, value interface{}, second time.Duration) string {n result, err := r.pool.Set(key, value, time.Duration(second)*time.Second).Result()n if err != nil {n log.Printf("set:%s value: %s 失败n", key, value)n return base.Emptyn }n return resultn}nn// Get 查询key的值n// @Description:n// @param keyn// @return stringn//nfunc (r RedisBase) Get(key string) string {n result, err := r.pool.Get(key).Result()n if err != nil {n log.Printf("get:%s 失败n", key)n return base.Emptyn }n return resultn}nn// GetSet 设置一个key的值,并返回这个key的旧值n// @Description:n// @param keyn// @param valuen// @return stringn//nfunc (r RedisBase) GetSet(key string, value interface{}) string {n result, err := r.pool.GetSet(key, value).Result()n if err != nil {n log.Printf("set:%s value: %s 失败n", key, value)n return base.Emptyn }n return resultn}nn// SetNX 如果key不存在,则设置这个key的值n// @Description:n// @param keyn// @param valuen// @param expirationn// @return booln//nfunc (r RedisBase) SetNX(key string, value interface{}, second int64) bool {n result, err := r.pool.SetNX(key, value, time.Duration(second)*time.Second).Result()n if err != nil {n log.Printf("set:%s value: %s 失败n", key, value)n return falsen }n return resultn}nn// MGet 批量查询key的值n// @Description:n// @param keyn// @param valuen// @param expirationn// @return booln//nfunc (r RedisBase) MGet(keys ...string) []interface{} {n result, err := r.pool.MGet(keys...).Result()n if err != nil {n log.Printf("获取 keys : %s 失败 %s", fmt.Sprint(keys), err.Error())n return niln }n return resultn}nn// MSet 批量设置key的值n// @Description:n// @param keysn// @return stringn//nfunc (r RedisBase) MSet(keys ...string) string {n result, err := r.pool.MSet(keys).Result()n if err != nil {n log.Printf("设置 keys : %s 失败 %s", fmt.Sprint(keys), err.Error())n return base.Emptyn }n return resultn}nn// Incr 针对一个key的数值进行递增操作n// @Description:n// @param keyn// @return stringn//nfunc (r RedisBase) Incr(key string) int64 {n result, err := r.pool.Incr(key).Result()n if err != nil {n log.Printf("自增 key: %s 失败 %s", key, err.Error())n return base.TEST_ERRORn }n return resultn}nn// IncrBy 针对一个key的数值进行递增操作n// @Description:n// @param keyn// @param valuen// @return stringn//nfunc (r RedisBase) IncrBy(key string, value int64) int64 {n result, err := r.pool.IncrBy(key, value).Result()n if err != nil {n log.Printf("自增 key: %s 失败 %s", key, err.Error())n return -1n }n return resultn}nn// Decr 针对一个key的数值进行递减操作n// @Description:n// @param keyn// @return stringn//nfunc (r RedisBase) Decr(key string) int64 {n result, err := r.pool.Decr(key).Result()n if err != nil {n log.Printf("自减 key: %s 失败 %s", key, err.Error())n return base.TEST_ERRORn }n return resultn}nn// DecrBy 针对一个key的数值进行递减操作n// @Description:n// @param keyn// @param valuen// @return stringn//nfunc (r RedisBase) DecrBy(key string, value int64) int64 {n result, err := r.pool.DecrBy(key, value).Result()n if err != nil {n log.Printf("自减 key: %s 失败 %s", key, err.Error())n return base.TEST_ERRORn }n return resultn}nn// Del 删除key操作,支持批量删除n// @Description:n// @param keysn// @return int64n//nfunc (r RedisBase) Del(keys ...string) int64 {n result, err := r.pool.Del(keys...).Result()n if err != nil {n log.Printf("删除 key: %s 失败 %s", fmt.Sprintln(keys), err.Error())n return base.TEST_ERRORn }n return resultn}nn// Expire 设置key的过期时间,单位秒n// @Description:n// @param keyn// @param secondn// @return booln//nfunc (r RedisBase) Expire(key string, second int64) bool {n result, err := r.pool.Expire(key, time.Duration(second)*time.Second).Result()n if err != nil {n log.Printf("设置 key: %s 过期时间失败 %s", fmt.Sprintln(key), err.Error())n return falsen }n return resultn}nn

API演示

基本上就是照着教程写完,然后再转成封装好的API实践,感觉更加清爽了,基本和Java版本的使用体验一致。

package testnnimport (n "funtester/db/redis"n "funtester/ftool"n "github.com/go-playground/assert/v2"n "log"n "strconv"n "testing"n)nnvar pool = redis.NewRdisPool("127.0.0.1:6379", 1)nnfunc TestRedis(t *testing.T) {n var str = "FunTester"n set := pool.Set("fun", str, 0)n log.Print(set)n get := pool.Get("fun")n assert.Equal(t, get, str)n getSet := pool.GetSet("fun", str+ftool.RandomStr(3))n log.Println(getSet)n pool.Set("aa", "32342", 0)n mGet := pool.MGet("fun", "aa")n for i, i2 := range mGet {n log.Printf("index :%d value : %sn", i, i2)n }n pool.Expire("fun", 300)n keys := pool.Keys("fu*")n for i, key := range keys {n log.Printf("index : %d, key : %s", i, key)n }n key := str + strconv.Itoa(ftool.RandomInt(1000))n pool.SetNX(key, "32432", 100)n log.Println(pool.Get(key))n log.Println("22222")n i := pool.MGet(str, key)n for _, i3 := range i {n log.Println(i3)n }n pool.MSet("aa", "111", "aabbbb", "22222")n pool.Incr("sum")n pool.IncrBy("sum", 10)n log.Println(pool.Get("sum"))n strings := pool.Keys("aa*")n for _, s := range strings {n log.Println(s)n }n pool.Decr("aa")n pool.Expire("sum", 100)n}nn

控制台输出

相对比较单调,只是确认一下实际效果,总体打印信息比较乱,不少方法不够熟练,各位将就看看。

2022/06/18 21:31:06 Redis 连接成功n2022/06/18 21:31:06 确认连接成功!n=== RUN TestRedisn2022/06/18 21:31:06 OKn2022/06/18 21:31:06 FunTestern2022/06/18 21:31:06 index :0 value : FunTesterc3Fn2022/06/18 21:31:06 index :1 value : 32342n2022/06/18 21:31:06 index : 0, key : funn2022/06/18 21:31:06 32432n2022/06/18 21:31:06 22222n2022/06/18 21:31:06 <nil>n2022/06/18 21:31:06 32432n2022/06/18 21:31:06 56n2022/06/18 21:31:06 aan2022/06/18 21:31:06 aabbbbn2022/06/18 21:31:06 aaaan--- PASS: TestRedis (0.00s)nPASSn

BUG挖掘机·性能征服者·头顶锅盖