go连接并简单操作redis

请添加图片描述


一、下载依赖库

go get github.com/go-redis/redis/v8

一、redis数据库的链接?

示例:

package main

import (
	"context"
	"github.com/go-redis/redis/v8"
)

var (
	ctx             = context.Background()
	linkRedisMethod sync.Once
	DbRedis         *redis.Client
)

func init() {
	initRedis()
}

// 连接redis数据库
// 且只会执行一次
func initRedis() {
	linkRedisMethod.Do(func() {
	//连接数据库
		DbRedis = redis.NewClient(&redis.Options{
			Addr:     "localhost:6379",   // 对应的ip以及端口号
			Password: "",				 // 数据库的密码
			DB:       0,				 // 数据库的编号,默认的话是0
		})
		// 连接测活
		_, err := DbRedis.Ping(ctx).Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("连接Redis成功")
	})
}

在这里我们使用sync.Once确保连接的唯一性,然后同时把这个将连接成功的实体用全局变量的形式保存方便后续的数据库的操作

还有一种用字符串连接的形式

opt, err := redis.ParseURL("redis://<user>:<pass>@localhost:6379/<db>")
if err != nil {
	panic(err)
}

rdb := redis.NewClient(opt)

二、简单的使用

1.string类型数据的插入查询

数据的插入

代码如下(示例):

// 用于向数据库中插入数据
// 并设置存活时间
func redisInsertStringData() {
	// 可设置该键值对存在的时间为 60s
	err := DbRedis.Set(ctx, "name", "yyy", 60*time.Second).Err()
	// 若设置为0那么将永久存活
	//err := DbRedis.Set(ctx, "name", "yyy", 0).Err()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println("数据插入成功")
	}
}

成功后可查看到对应键值对数据成功被插入,以及对应的存活时间(TTlL对应的)
在这里插入图片描述

数据的查询

// 用于查询数据
// 查询的是string类型的数据
func redisQuary() {
	val, err := DbRedis.Get(ctx, "name").Result()
	// redis.Nil 用于判断是否查询到有该组数据
	if err == redis.Nil {
		// do something
		fmt.Println("key 不存在")
	} else if err != nil {
		// 失败处理
		panic(err)
	} else {
		// 查询成功后处理
		fmt.Println("val -> ", val)
	}
}

2.struct类型数据的插入查询

代码如下(示例):

type Model struct {
	Str1 string `json:"str1"`
	Str2 string `json:"str2"`
}

// 需要为对象天剑该方法,否则会报错
func (m *Model) MarshalBinary() (data []byte, err error) {
	return json.Marshal(m)
}

func (m *Model) UnmarshalBinary(data []byte) error {
	return json.Unmarshal(data, m)
}

// 用于插入结构体
// 但是结构体上需要添加 MarshalBinary 方法
func InsertStrcutData() {
	err := DbRedis.Set(ctx, "key", &Model{
		"ywh",
		"12",
	}, time.Minute).Err()
	if err != nil {
		panic(err)
	} else {
		fmt.Println("插入成功")
	}
}

要注意的是这里需要给对象添加上MarshalBinary这个方法用于将struct类型转成 []byte 类型。

** 数据的查询 **

// 查询结构体的数据
func redisQueryStrcutData() {
	data, err := DbRedis.Do(ctx, "get", "key").Result()
	if err == redis.Nil {
		fmt.Println("不存在这个Key")
	} else if err != nil {
		panic("查找失败")
	} else {
		fmt.Printf("data=> %T\n", data)
		var myModel Model
		json.Unmarshal([]byte(data.(string)), &myModel)
		fmt.Printf("data-> %+v", myModel)
	}
}

输出的结果
在这里插入图片描述

3. map类型数据的插入查询

数据插入

// 插入map类型的数据
func InsertMapData() {
	data := make(map[string]string)
	data["name"] = "Ywh"
	data["age"] = "Age"

	err := DbRedis.HSet(ctx, "testData2", data).Err()
	if err != nil {
		panic(err)
	} else {
		fmt.Println("插入数据成功")
	}
}

数据查询


// 查询hash数据
func redisQueryMapData() {
	// 查询整个map 返回的是map[string]...
	data, err := DbRedis.HGetAll(ctx, "testData2").Result()

	// 查询的是其中的一个值
	hashGet, _ := DbRedis.HGet(ctx, "testData2", "age").Result()
	fmt.Println("HGet age", hashGet)
	if err == redis.Nil {
		fmt.Println("不存在这个key")
	} else if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("data -> %+v\n", data)
	}
}

  • HGetAll的方法可以根据key查询到对应的整个map对象
  • HGet的方法可以查询到其中一个属性的数据

4.List 数据的插入删除

// list 数据的操作
func redisInsertListData() {
	// 插入list数据
	// Lpush是插入到首部
	// Rpush 是插入尾部
	DbRedis.LPush(ctx, "ListDemo", "首部").Err()
	DbRedis.RPush(ctx, "ListDemo", "尾部").Err()

	// 去除并且移除左边第一个元素
	// 对应的有 RPop可以去除并且移除list中的最后一个元素
	first, err := DbRedis.LPop(ctx, "ListDemo").Result()
	if err == redis.Nil {
		fmt.Println("未查找到该数据")
	} else if err != nil {
		panic(err)
	} else {
		fmt.Println(first)
	}

	//去除并且移除左边第一个元素 跟上面那种不同的是,如果这个列表没有元素会阻塞列表然后等待超时
	// 对应的有BRPop 可以是操作list中最后一个元素的
	first2, _ := DbRedis.BLPop(ctx, time.Second*10, "ListDemo").Result()
	fmt.Printf("key:%s  val:%s\n", first2[0], first2[1])

	// 查询出list中指定位置的元素
	listIndexData, _ := DbRedis.LIndex(ctx, "ListDemo", 1).Result()
	fmt.Println("listData", listIndexData)

	// 查询出列表的长度
	listLen, _ := DbRedis.LLen(ctx, "ListDemo").Result()
	fmt.Println("listLen", listLen)

	// 获取列表
	// 按照索引的范围进行查找数据
	listData, _ := DbRedis.LRange(ctx, "ListDemo", 1, 2).Result()
	fmt.Println("listData", listData)	
}

一些基本操作的API

方法名作用
LPushList 首插
RPushList 尾插
LIndex从左向右查找List指定位置的数据
LPopList左侧的首个元素pop
RPopList右侧的首个元素pop
LLen查询List 的长度
LRange查询出List中指定范围的数据

5.操作set

// set 是string类型的无需的集合
func RedisTestSet() {
	setKey := "setKey"

	// 向set中插入值
	DbRedis.SAdd(ctx, setKey, "set1")
	DbRedis.SAdd(ctx, setKey, "set2")
	DbRedis.SAdd(ctx, setKey, "set3")

	setList, _ := DbRedis.SMembers(ctx, setKey).Result()
	fmt.Println(setList)

	// 删除set中的一个值
	DbRedis.SRem(ctx, "set1")

	// 删除并且返回set 的一个随机元素
	setFirst, _ := DbRedis.SPop(ctx, setKey).Result()
	fmt.Println(setFirst)
}

6.操作zset

// (zset) 操作有序的set
func TestRestZset() {
	zSetKey := "zSetKey"
	people := []*redis.Z{
		&redis.Z{Score: 20, Member: "张三"},
		&redis.Z{Score: 50, Member: "老王"},
		&redis.Z{Score: 100, Member: "李四"},
		&redis.Z{Score: 20, Member: "小黄"},
	}

	// 想zset中插入数据
	DbRedis.ZAdd(ctx, zSetKey, people...)

	// 给指定的元素指定score
	newScore, _ := DbRedis.ZIncrBy(ctx, zSetKey, 5.0, "张三").Result()
	fmt.Println("张三的newScore ->", newScore)

	// 查询zset中Score前两名的数据
	zsetListData, _ := DbRedis.ZRevRangeWithScores(ctx, zSetKey, 0, 1).Result()
	fmt.Println(zsetListData)

	// 移除分数最低的两个数据,返回的是成功移除的条数
	zsetListData2, _ := DbRedis.ZRemRangeByRank(ctx, zSetKey, 0, 0).Result()
	fmt.Println(zsetListData2)

}

7.设置过期时间

在给定的包里面,只有string类型的数据设定的时候可以直接通过传参的方式设定过期时间,而其他的数据类型也可以通过其他的
额外的操作来设定对应的过期时间

// 设置过期时间
func setTime() {
	// 设置过期时间为30秒
	DbRedis.Expire(ctx, "name", time.Second*30)
	DbRedis.ExpireAt(ctx, "name", time.Now().Add(time.Second*100))

	duration, err := DbRedis.TTL(ctx, "name").Result()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("key%v的有效时间,%v,%v \n", "name", duration.String(), duration.Seconds())

}

8.自定义命令

val, err := rdb.Do(ctx, "get", "key").Result()
if err != nil {
	if err == redis.Nil {
		fmt.Println("key does not exists")
		return
	}
	panic(err)
}
fmt.Println(val.(string))

参考

  • https://redis.uptrace.dev/guide/ring.html#introduction
  • https://segmentfault.com/a/1190000021702953
  • https://github.com/go-redis/redis

总结

总体来说geo-redis对提供的api对于支持redis 的操作比较简单方便。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐