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
方法名 | 作用 |
---|---|
LPush | List 首插 |
RPush | List 尾插 |
LIndex | 从左向右查找List指定位置的数据 |
LPop | List左侧的首个元素pop |
RPop | List右侧的首个元素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 的操作比较简单方便。