go-redis

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go-redis相关的知识,希望对你有一定的参考价值。

go-redis

0.基本使用

package main

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

func main() 
	ctx := context.Background()
	rdb := redis.NewClient(&redis.Options
		Addr:      "localhost:6379",
		Password: "", // no password set
		DB:          0, // use default DB
	)
	fmt.Println(rdb)
	// Redis<localhost:6379 db:0>

	// 执行命令
	err := rdb.Set(ctx, "key", "value", 0).Err()
	if err != nil 
		panic(err)
	

	val, err := rdb.Get(ctx, "key").Result()
	if err != nil 
		panic(err)
	
	fmt.Println("key", val)  // key value
	val2, err := rdb.Get(ctx, "key2").Result()
	if err == redis.Nil 
		fmt.Println("key2 does not exist")
	 else if err != nil 
		panic(err)
	 else 
		fmt.Println("key2", val2)
		//key2 does not exist
	

1.操作String类型

操作redis String类型

String 类型是 Redis 中最基本的数据类型,string 类型的值最大能存储 512MB。

下面是go-redis操作String字符串类型的一些API:

  • Set:设置字符串的值
  • SetEX:设置并指定过期时间(set expire)
  • SetNX:设置并指定过期时间(if not exists) 如果key已经存在,则返回err
  • Get:获取字符串的值
  • GetRange:获取字符串值的子字符

这些API的演示代码如下:

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/go-redis/redis/v8"
)

func main() 
	ctx := context.Background()

	rdb := redis.NewClient(&redis.Options
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	)
	_, err := rdb.Ping(ctx).Result() // PING, <nil>
	if err != nil 
		fmt.Println("connect redis failed:", err)
		return
	

	// Set 设置
	err = rdb.Set(ctx, "key", "thisisavalue", 0).Err() // 0表示永不过期
	if err != nil 
		panic(err)
	
	err = rdb.Set(ctx, "key2", "this is a value2", time.Minute*2).Err() // key2将会在两分钟后过期失效
	if err != nil 
		panic(err)
	
	fmt.Println("set success")

	// SetEX 设置并指定过期时间
	err = rdb.SetEX(ctx, "key3", "this is a value3", time.Hour*2).Err()
	if err != nil 
		panic(err)
	
	fmt.Println("SetEX success")

	// SetNX 设置并指定过期时间(如果key已经存在返回err
	_, err = rdb.SetNX(ctx, "key4", "this is a value4", time.Minute).Result()
	if err != nil 
		fmt.Println("SetNX failed, key4已经存在", err)
	
	fmt.Println("SetNX success")

	// Get 获取
	result, err := rdb.Get(ctx, "key").Result()
	if err != nil 
		panic(err)
	
	fmt.Println("key值:", result)

	result, err = rdb.Get(ctx, "key5").Result()
	// redis.Nil来区分空字符串应答和Nil应答(键不存在)
	if err == redis.Nil 
		fmt.Println("key5不存在")
	 else if err != nil 
		panic(err)
	 else 
		fmt.Println("key5值为:", result)
	

	// GetRange 获取字符串值的子字符
	result, err = rdb.GetRange(ctx, "key", 1, 4).Result()
	if err != nil 
		panic(err)
	
	fmt.Printf("GetRange截取key值为: %v\\n", result)


// 打印结果如下:
/*
set success
SetEX success
SetNX success
key值: thisisavalue
key5不存在
GetRange截取key值为: hisi
*/


下面是增减量的API:

  • Incr:将 key 中储存的数字值增加1
  • IncrBy:将 key 所储存的值加上给定的增量值
  • Decr:将 key 中储存的数字值减1
  • DecrBy:key 所储存的值减去给定的减量值

这些API的演示代码如下:

package main

import (
	"context"
	"fmt"

	"github.com/go-redis/redis/v8"
)

func main() 
	ctx := context.Background()

	rdb := redis.NewClient(&redis.Options
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	)
	_, err := rdb.Ping(ctx).Result()  // PING, <nil>
	if err != nil 
		fmt.Println("connect redis failed:", err)
		return
	

	// Incr 增加+1
	result, err := rdb.Incr(ctx, "count").Result()
	if err != nil 
		panic(err)
	
	fmt.Printf("count值为: %v\\n", result)

	// IncrBy 按指定步长增加
	result, err = rdb.IncrBy(ctx, "count", 2).Result()
	if err != nil 
		panic(err)
	
	fmt.Printf("count值为: %v\\n", result)

	// Decr 减少-1
	result, err = rdb.Decr(ctx, "count").Result()
	if err != nil 
		panic(err)
	
	fmt.Printf("count值为: %v\\n", result)

	// DecrBy 按指定步长减少
	result, err = rdb.DecrBy(ctx, "count", 2).Result()
	if err != nil 
		panic(err)
	
	fmt.Printf("count值为: %v\\n", result)


// 打印结果如下:
/*
count值为: 1
count值为: 3
count值为: 2
count值为: 0
*/

2.操作List类型

Redis 列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边)。

下面是go-redis操作redis List列表类型的一些API:

  • LPush:在列表的左侧加入数据
  • LLen:获取链表元素个数
  • LIndex:获取列表某下标对应元素
  • LInsert:向某个索引位置插入一个元素
  • LSet:设置列表某个索引位置的值
  • Lpop:从列表左侧弹出数据
  • LRange:获取某个索引范围里的元素
  • LTrim:对一个列表进行修剪,只让列表保留指定区间内的元素,不在指定区间之内的元素都将被删除
package main

import (
	"context"
	"fmt"

	"github.com/go-redis/redis/v8"
)

func main() 
	ctx := context.Background()

	rdb := redis.NewClient(&redis.Options
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	)
	_, err := rdb.Ping(ctx).Result()  // PING, <nil>
	if err != nil 
		fmt.Println("connect redis failed:", err)
		return
	
	result, err := rdb.Exists(ctx, "test_list").Result()
	if err != nil 
		return
	
	if result == 1
		fmt.Println("test_list have existed ")
		value, err := rdb.Del(ctx,"test_list").Result()
		if err != nil 
			return
		
		if value ==1 
			fmt.Println("test_list delete success!")
		
	
	// LPush(ctx, key, values...) 在列表的左侧加入数据
	n, err := rdb.LPush(ctx, "test_list", 1, 2, 3, 4, 5, 6).Result()
	if err != nil 
		panic(err)
	
	fmt.Println(n)

	// LLen(ctx, key) 获取链表元素个数
	len, err := rdb.LLen(ctx, "test_list").Result()
	if err != nil 
		panic(err)
	
	fmt.Println("test_list的长度:", len)

	// LIndex(ctx, key, index) 获取列表某下标对应元素
	val, err := rdb.LIndex(ctx, "test_list", 2).Result()  // 索引从0数起。
	if err != nil 
		panic(err)
	
	// 6 5 4 3 2 1
	fmt.Println("index是2的值:", val)

	// LInsert(ctx, key, op, pivot, value) 向某个索引位置插入一个元素
	err = rdb.LInsert(ctx, "test_list", "before", "2", 8).Err() // 在test_list列表的2的前面插入8。
	if err != nil 
		panic(err)
	
	// 6 5 4 3 8 2 1
	fmt.Println("插入成功")

	// LSet(ctx, key, index, value) 设置列表某个索引位置的值
	err = rdb.LSet(ctx, "test_list", 1, 9).Err()  // 给索引为1 的位置设置为9。索引从0数起。
	if err != nil 
		panic(err)
	
	fmt.Println("设置成功")
	fmt.Println(rdb.LRange(ctx,"test_list",0,-1).Result())
	// 6 9 4 3 8 2 1
	// LPop(ctx, key) 从列表左侧弹出数据
	val, err = rdb.LPop(ctx, "test_list").Result()
	if err != nil 
		panic(err)
	
	fmt.Println("从列表左侧弹出元素:", val)
	// 9 4 3 8 2 1
	// LRange(ctx, key, start, stop) 获取某个索引范围里的元素
	vals, err := rdb.LRange(ctx, "test_list", 1, 4).Result()
	if err != nil 
		panic(err)
	
	fmt.Println("获取索引1到4的值:", vals)

	// LTrim(ctx, key, start, stop) 对一个列表进行修剪,
	// 只让列表保留指定区间内的元素,不在指定区间之内的元素都将被删除
	val, err = rdb.LTrim(ctx, "test_list", 1, 4).Result()  // 此时只剩下1到4范围内的值
	if err != nil 
		panic(err)
	
	fmt.Println("val值:", val)


// 打印结果如下:
/*
test_list have existed 
test_list delete success!
6
test_list的长度: 6
index是2的值: 4
插入成功
设置成功
[6 9 4 3 8 2 1] <nil>
从列表左侧弹出元素: 6
获取索引1到4的值: [4 3 8 2]
val值: OK
*/

3.操作redis Hash类型

Redis hash 是一个键值(key=>value)对集合。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

下面是go-redis操作redis Hash类型的一些API:

  • HSet:给key设置field和value
  • HGet:获取key某个field的value
  • HMset:给key批量设置field和value
  • HLen:获取键值对个数
  • HGetAll:获取全部键值对元素
  • HKeys:获取所有的key
  • HIncrBy:增加,成功返回增加后的值
  • HDel:删除键值对元素
  • HExists:检查key某个field是否存在
package main

import (
	"context"
	"fmt"

	"github.com/go-redis/redis/v8"
)

func main() 
	ctx := context.Background()

	rdb := redis.NewClient(&redis.Options
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	)
	_, err := rdb.Ping(ctx).Result()  // PING, <nil>
	if err != nil 
		fmt.Println("connect redis failed:", err)
		return
	

	// HSet 给key设置field和value
	result, err := rdb.HSet(ctx, "user1", "name", "zhangsan").Result()
	if err != nil 
		panic(err)
	
	fmt.Println(result)  // 1

	// HMSet 批量设置
	rdb.HMSet(ctx, "user1", map[string]interface"age": 18, "sex": "male")

	// HGet 获取某个field的value
	name, err := rdb.HGet(ctx, "user1", "name").Result()
	if err != nil 
		panic(err)
	
	fmt.Println(name)  // zhangsan

	// HMGet 批量获取field的value
	fields, err := rdb.HMGet(ctx, "user1", "name", "age").Result()
	if err != nil 
		panic(err)
	
	fmt.Println(fields)  // [zhangsan 18]

	// HLen 获取键值对个数
	len, err := rdb.HLen(ctx, "user1").Result()
	if err != nil 
		panic(err)
	
	fmt.Println(len)  // 3

	// HGetAll 获取全部元素
	all, err := rdb.HGetAll(ctx, "user1").Result()
	if err != nil 
		panic(err)
	
	fmt.Println(all)  // map[age:18 name:zhangsan sex:male]

	// HKeys 获取所有的key
	keys, err := rdb.HKeys(ctx, "user1").Result()
	if err != nil 
		panic(err)
	
	fmt.Println(keys)  // [name age sex]

	// HIncrBy 增加,成功返回增加后的值
	age, err := rdb.HIncrBy(ctx, "user1", "age", 2).Result()
	if err != nil 
		panic(err)
	
	fmt.Println(age)  // 20

	// HDel 删除键值对元素
	result, err = rdb.HDel(ctx, "user1", "name").Result()
	if err != nil 
		panic(err)
	
	fmt.Println(result)  // 1

	// HExists 检查某个元素是否存在
	fmt.Println(rdb.HExists(ctx, "user1","name"))  // hexists user1 name: false


// 打印结果如下:
/*
1
zhangsan
[zhangsan 18]
3
map[age:18 name:zhangsan sex:male]
[name age sex]
20
1
hexists user1 name: false
*/

4.操作redis Set类型

Redis 的 Set 是 string 类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

下面是go-redis操作redis Set集合类型的一些API:

  • SAdd:向指定集合添加集合元素
  • SSMembers:获取集合中的所有成员
  • SCard:获取集合中成员的数量
  • SIsMember:判断某成员是否在集合中
  • SRem:删除集合里指定成员
  • SPop:随机从集合中弹出一个元素
package main

import (
  "context"
  "fmt"

  "github.com/go-redis/redis/v8"
)

func main() 
  ctx := context.Background()
  
  rdb := redis.NewClient(&redis.Options
    Addr:     "localhost:6379",
    Password: "",
    DB:       0,
  )
  _, err := rdb.Ping(ctx).Result()  // PING, <nil>
  if err != nil 
    fmt.Println("connect redis failed:", err)
    return
  
  
  // SAdd 向指定集合添加集合元素
  result, err := rdb.SAdd(ctx,以上是关于go-redis的主要内容,如果未能解决你的问题,请参考以下文章

go-redis cluster 使用demo

golang常用库包:缓存redis操作库go-redis使用(03)-高级数据结构和其它特性

go-redis 连接池实现思想

go-redis 基于beego正确使用序列化存储数据和反序列化获取数据

如何从golang go-redis中的redis.Cmder获取价值?

Go语言连接Redis之go-redis使用指南