写点什么

Go 语言 Redis API 基本功能实践

作者:FunTester
  • 2022 年 6 月 23 日
  • 本文字数:4322 字

    阅读完需:约 14 分钟

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

API 演示

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


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

控制台输出

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


2022/06/18 21:31:06 Redis 连接成功2022/06/18 21:31:06 确认连接成功!=== RUN   TestRedis2022/06/18 21:31:06 OK2022/06/18 21:31:06 FunTester2022/06/18 21:31:06 index :0  value : FunTesterc3F2022/06/18 21:31:06 index :1  value : 323422022/06/18 21:31:06 index : 0, key : fun2022/06/18 21:31:06 324322022/06/18 21:31:06 222222022/06/18 21:31:06 <nil>2022/06/18 21:31:06 324322022/06/18 21:31:06 562022/06/18 21:31:06 aa2022/06/18 21:31:06 aabbbb2022/06/18 21:31:06 aaaa--- PASS: TestRedis (0.00s)PASS
复制代码


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



阅读原文,跳转我的仓库地址

发布于: 刚刚阅读数: 3
用户头像

FunTester

关注

公众号:FunTester,800篇原创,欢迎关注 2020.10.20 加入

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

评论

发布
暂无评论
Go语言Redis API基本功能实践_FunTester_InfoQ写作社区