Go 语言开发] redis 简单易用
最编程
2024-03-11 19:26:45
...
本文主要介绍redis安装和使用。首先安装redis依赖库,这里是v8版本;然后连接redis,完成基本配置;最后测试封装的工具类
文章目录
- 安装redis依赖库
- 连接redis和配置
- 工具类封装
- 代码测试
欢迎大家访问个人博客网址:https://www.maogeshuo.com,博主努力更新中…
参考文件:
- Yaml文件配置,Config使用
- Log日志封装
- 常用工具类封装
安装redis依赖库
命令行安装redis
go get github.com/go-redis/redis/v8
连接redis和配置
首先创建了一个 Redis 客户端,并连接到本地 Redis 服务器(默认端口为 6379)。连接完成后,使用Ping函数测试连接是否成功。
package core
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"time"
)
// https://zhuanlan.zhihu.com/p/637537337
// https://blog.****.net/qq_44237719/article/details/128920821
var Redis *RedisClient
type RedisClient struct {
client *redis.Client
ctx context.Context
}
// InitRedis 初始化redis
func InitRedis() {
redisConfig := Config.Redis
client := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", redisConfig.Host, redisConfig.Port),
Password: redisConfig.Password,
DB: redisConfig.Db,
})
redisClient := &RedisClient{
client: client,
ctx: context.Background(),
}
Redis = redisClient
_, err := client.Ping(client.Context()).Result()
if err != nil {
LOG.Println("redis连接失败!")
return
}
LOG.Println("redis连接成功!")
}
工具类封装
/*------------------------------------ 字符 操作 ------------------------------------*/
// Set 设置 key的值
func (this *RedisClient) Set(key, value string) bool {
result, err := this.client.Set(this.ctx, key, value, 0).Result()
if err != nil {
LOG.Println(err)
return false
}
return result == "OK"
}
// SetEX 设置 key的值并指定过期时间
func (this *RedisClient) SetEX(key, value string, ex time.Duration) bool {
result, err := this.client.Set(this.ctx, key, value, ex).Result()
if err != nil {
LOG.Println(err)
return false
}
return result == "OK"
}
// Get 获取 key的值
func (this *RedisClient) Get(key string) (bool, string) {
result, err := this.client.Get(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
return false, ""
}
return true, result
}
// GetSet 设置新值获取旧值
func (this *RedisClient) GetSet(key, value string) (bool, string) {
oldValue, err := this.client.GetSet(this.ctx, key, value).Result()
if err != nil {
LOG.Println(err)
return false, ""
}
return true, oldValue
}
// Incr key值每次加一 并返回新值
func (this *RedisClient) Incr(key string) int64 {
val, err := this.client.Incr(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
}
return val
}
// IncrBy key值每次加指定数值 并返回新值
func (this *RedisClient) IncrBy(key string, incr int64) int64 {
val, err := this.client.IncrBy(this.ctx, key, incr).Result()
if err != nil {
LOG.Println(err)
}
return val
}
// IncrByFloat key值每次加指定浮点型数值 并返回新值
func (this *RedisClient) IncrByFloat(key string, incrFloat float64) float64 {
val, err := this.client.IncrByFloat(this.ctx, key, incrFloat).Result()
if err != nil {
LOG.Println(err)
}
return val
}
// Decr key值每次递减 1 并返回新值
func (this *RedisClient) Decr(key string) int64 {
val, err := this.client.Decr(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
}
return val
}
// DecrBy key值每次递减指定数值 并返回新值
func (this *RedisClient) DecrBy(key string, incr int64) int64 {
val, err := this.client.DecrBy(this.ctx, key, incr).Result()
if err != nil {
LOG.Println(err)
}
return val
}
// Del 删除 key
func (this *RedisClient) Del(key string) bool {
result, err := this.client.Del(this.ctx, key).Result()
if err != nil {
return false
}
return result == 1
}
// Expire 设置 key的过期时间
func (this *RedisClient) Expire(key string, ex time.Duration) bool {
result, err := this.client.Expire(this.ctx, key, ex).Result()
if err != nil {
return false
}
return result
}
/*------------------------------------ list 操作 ------------------------------------*/
// LPush 从列表左边插入数据,并返回列表长度
func (this *RedisClient) LPush(key string, date ...interface{}) int64 {
result, err := this.client.LPush(this.ctx, key, date).Result()
if err != nil {
LOG.Println(err)
}
return result
}
// RPush 从列表右边插入数据,并返回列表长度
func (this *RedisClient) RPush(key string, date ...interface{}) int64 {
result, err := this.client.RPush(this.ctx, key, date).Result()
if err != nil {
LOG.Println(err)
}
return result
}
// LPop 从列表左边删除第一个数据,并返回删除的数据
func (this *RedisClient) LPop(key string) (bool, string) {
val, err := this.client.LPop(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
return false, ""
}
return true, val
}
// RPop 从列表右边删除第一个数据,并返回删除的数据
func (this *RedisClient) RPop(key string) (bool, string) {
val, err := this.client.RPop(this.ctx, key).Result()
if err != nil {
fmt.Println(err)
return false, ""
}
return true, val
}
// LIndex 根据索引坐标,查询列表中的数据
func (this *RedisClient) LIndex(key string, index int64) (bool, string) {
val, err := this.client.LIndex(this.ctx, key, index).Result()
if err != nil {
LOG.Println(err)
return false, ""
}
return true, val
}
// LLen 返回列表长度
func (this *RedisClient) LLen(key string) int64 {
val, err := this.client.LLen(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
}
return val
}
// LRange 返回列表的一个范围内的数据,也可以返回全部数据
func (this *RedisClient) LRange(key string, start, stop int64) []string {
vales, err := this.client.LRange(this.ctx, key, start, stop).Result()
if err != nil {
LOG.Println(err)
}
return vales
}
// LRem 从列表左边开始,删除元素data, 如果出现重复元素,仅删除 count次
func (this *RedisClient) LRem(key string, count int64, data interface{}) bool {
_, err := this.client.LRem(this.ctx, key, count, data).Result()
if err != nil {
fmt.Println(err)
}
return true
}
// LInsert 在列表中 pivot 元素的后面插入 data
func (this *RedisClient) LInsert(key string, pivot int64, data interface{}) bool {
err := this.client.LInsert(this.ctx, key, "after", pivot, data).Err()
if err != nil {
LOG.Println(err)
return false
}
return true
}
/*------------------------------------ set 操作 ------------------------------------*/
// SAdd 添加元素到集合中
func (this *RedisClient) SAdd(key string, data ...interface{}) bool {
err := this.client.SAdd(this.ctx, key, data).Err()
if err != nil {
LOG.Println(err)
return false
}
return true
}
// SCard 获取集合元素个数
func (this *RedisClient) SCard(key string) int64 {
size, err := this.client.SCard(this.ctx, "key").Result()
if err != nil {
LOG.Println(err)
}
return size
}
// SIsMember 判断元素是否在集合中
func (this *RedisClient) SIsMember(key string, data interface{}) bool {
ok, err := this.client.SIsMember(this.ctx, key, data).Result()
if err != nil {
LOG.Println(err)
}
return ok
}
// SMembers 获取集合所有元素
func (this *RedisClient) SMembers(key string) []string {
es, err := this.client.SMembers(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
}
return es
}
// SRem 删除 key集合中的 data元素
func (this *RedisClient) SRem(key string, data ...interface{}) bool {
_, err := this.client.SRem(this.ctx, key, data).Result()
if err != nil {
LOG.Println(err)
return false
}
return true
}
// SPopN 随机返回集合中的 count个元素,并且删除这些元素
func (this *RedisClient) SPopN(key string, count int64) []string {
vales, err := this.client.SPopN(this.ctx, key, count).Result()
if err != nil {
LOG.Println(err)
}
return vales
}
/*------------------------------------ hash 操作 ------------------------------------*/
// HSet 根据 key和 field字段设置,field字段的值
func (this *RedisClient) HSet(key, field, value string) bool {
err := this.client.HSet(this.ctx, key, field, value).Err()
if err != nil {
return false
}
return true
}
// HGet 根据 key和 field字段,查询field字段的值
func (this *RedisClient) HGet(key, field string) string {
val, err := this.client.HGet(this.ctx, key, field).Result()
if err != nil {
LOG.Println(err)
}
return val
}
// HMGet 根据key和多个字段名,批量查询多个 hash字段值
func (this *RedisClient) HMGet(key string, fields ...string) []interface{} {
vales, err := this.client.HMGet(this.ctx, key, fields...).Result()
if err != nil {
panic(err)
}
return vales
}
// HGetAll 根据 key查询所有字段和值
func (this *RedisClient) HGetAll(key string) map[string]string {
data, err := this.client.HGetAll(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
}
return data
}
// HKeys 根据 key返回所有字段名
func (this *RedisClient) HKeys(key string) []string {
fields, err := this.client.HKeys(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
}
return fields
}
// HLen 根据 key,查询hash的字段数量
func (this *RedisClient) HLen(key string) int64 {
size, err := this.client.HLen(this.ctx, key).Result()
if err != nil {
LOG.Println(err)
}
return size
}
// HMSet 根据 key和多个字段名和字段值,批量设置 hash字段值
func (this *RedisClient) HMSet(key string, data map[string]interface{}) bool {
result, err := this.client.HMSet(this.ctx, key, data).Result()
if err != nil {
LOG.Println(err)
return false
}
推荐阅读
-
最简单易懂的 C 语言开发环境构建教程,分分钟教你如何在 Windows 中运行第一个 Hello World 程序!
-
简单易用的 Android 开发 GreenDAO 数据库
-
如何在 Go 语言开发中执行单元测试和集成测试
-
从零开始建立一个用 Go 语言开发的个人网站
-
纯干货分享 | 研发效能提升——敏捷需求篇-而敏捷需求是提升效能的方式中不可或缺的模块之一。 云智慧的敏捷教练——Iris Xu近期在公司做了一场分享,主题为「敏捷需求挖掘和组织方法,交付更高业务价值的产品」。Iris具有丰富的团队敏捷转型实施经验,完成了企业多个团队从传统模式到敏捷转型的落地和实施,积淀了很多的经验。 这次分享主要包含以下2个部分: 第一部分是用户影响地图 第二部分是事件驱动的业务分析Event driven business analysis(以下简称EDBA) 用户影响地图,是一种从业务目标到产品需求映射的需求挖掘和组织的方法。 在软件开发过程中可能会遇到一些问题,比如大家使用不同的业务语言、技术语言,造成角色间的沟通阻碍,还会导致一些问题,比如需求误解、需求传递错误等;这会直接导致产品的功能需求和要实现的业务目标不是映射关系。 但在交付期间,研发人员必须要将这些需求实现交付,他们实则并不清楚这些功能需求产生的原因是什么、要解决客户的哪些痛点。研发人员往往只是拿到了解决方案,需要把它实现,但没有和业务侧一起去思考解决方案是否正确,能否真正的帮助客户解决问题。而用户影响地图通常是能够连接业务目标和产品功能的一种手段。 我们在每次迭代里加入的假设,也就是功能需求。首先把它先实现,再逐步去验证我们每一个小目标是否已经实现,再看下一个目标要是什么。那影响地图就是在这个过程中帮我们不断地去梳理目标和功能之间的关系。 我们在软件开发中可能存在的一些问题 针对这些问题,我们如何避免?先简单介绍做敏捷转型的常规思路: 先做团队级的敏捷,首先把产品、开发、测试人员,还有一些更后端的人员比如交互运维的同学放在一起,组成一个特训团队做交付。这个团队要包含交付过程中所涉及的所有角色。 接着业务敏捷要打通整个业务环节和研发侧的一个交付。上图中可以看到在敏捷中需求是分层管理的,第一层是业务需求,在这个层级是以用户目标和业务目标作为输入进行规划,同时需要去考虑客户的诉求。业务人员通过获取到的业务需求,进一步的和团队一起将其分解为产品需求。所以业务需求其实是我们真正去发布和运营的单元,它可以被独立发布到我们的生产环境上。我们的产品需求其实就是产品的具体功能,它是我们集成和测试的对象,也就是我们最终去部署到系统上的一个基本单元。产品需求再到了我们的开发团队,映射到迭代计划会上要把它分解为相应的技术任务,包括我们平时所说的比如一些前端的开发、后端的开发、测试都是相应的技术任务。所以业务敏捷要达到的目标是需要去持续顺畅高质量的交付业务价值。 将这几个点串起来,形成金字塔结构。最上层我们会把业务目标放在整个金字塔的塔尖。这个业务目标是通过用户的目标以及北极星指标确立的。确认业务目标后再去梳理相应的业务流程,最后生产。另外产品需求包含了操作流程和业务规则,具需求交付时间、工程时间以及我们的一些质量标准的要求。 谈到用户影响的地图,在敏捷江湖上其实有一个传说,大家都有一个说法叫做敏捷需求的“任督二脉”。用户影响地图其实就是任脉,在黑客马拉松上用过的用户故事地图其实叫督脉。所以说用户影响地图是在用户故事地图之前,先帮我们去梳理出我们要做哪些东西。当我们真正识别出我们要实现的业务活动之后,用户故事地图才去梳理我们整个的业务工作流,以及每个工作流节点下所要包含的具体功能和用户故事。所以说用户影响地图需要解决的问题,我们包括以下这些: 首先是范围蔓延,我们在整张地图上,功能和对应的业务目标是要去有一个映射的。这就避免了一些在我们比如有很多干系人参与的会议上,那大家都有不同想法些立场,会提出很多需求(正确以及错误的需求)。这个时候我们会依据目标去看这些需求是否真的是会影响我们的目标。 这里提到的错误需求,比如是利益相关的人提出的、客户认为产品应该有的、某个产品经理需求分析师认为可以有的....但是这些功能在用户影响地图中匹配不到对应目标的话,就需要降低优先级或弃掉。另外,通常我们去制定解决方案的时候,会考虑较完美的实现,导致解决方案括很多的功能。这个时候关键目标至关重要,会帮助我们梳理筛选、确定优先级。 看一下用户影响到地图概貌 总共分为一个三层的结构: 第一层why,你的业务目标哪个是最重要的,为什么?涉及到的角色有哪些? 第二层how ,怎样产生影响?影响用户角色什么样的行为? (不需要去列出所有的影响,基于业务目标) 第三层what,最关键的是在梳理需求时不需一次把所有细节想全,这通常团队中经常遇到的问题。 我们用这个例子来看一下 这是一个客服中心的影响地图,业务目标是 3个月内不增加客服人数的前提下能支持1.5倍的用户数。此业务目标设定是符合 smart 原则的,specific非常的具体,miserable 是可以衡量的,action reoriented是面向活动的, real list 也是很实际的。 量化的目标会指引我们接下来的行动,梳理一个业务目标,尽量去量化,比如 :我们通过打造一条什么样的流水线,能够提高整个部署的效率,时间是原来的 1/2 。这样才是一个能量化的有意义的目标。 回到这幅图, how 层级识别出来的内容,客服角色:想要对它施加的影响,把客户引导到论坛上,帮助客户更容易的跟踪问题,更快速的去定位问题。初级用户:方论坛上找到问题。高级用户:在论坛上回答问题。通过我们这些用户角色,进行活动,完成在不增加客户客服人数的前提下支持更多的用户数量。 最后一个层级,才是我们日常接触比较多的真正的功能的特性和需求,比如引导到客户到论坛上,其实这个产品就需要有一个常见问题的论坛的链接。这个层次需要我们团队进一步地在交付,在每个迭代之前做进一步的梳理,细化成相应的用户故事。 这个是云智慧团队中,自己做的影响地图的范例,可以看下整个的层级结构。序号表示优先级。 那我们用户影响地图可以总结为:
-
Win7 go 语言开发环境构建(64 位)
-
Go 网络部分:从零开始构建最简单的 Go 语言 Web 服务器
-
如何使用 Go 语言进行量化交易开发?
-
基于 gin_scaffold 用 Go 语言开发网络项目
-
[Golang 星图]提高开发速度:使用 Go 语言的文本和字符串处理工具提高开发效率