分享
  1. 首页
  2. 文章

golang 操作redis5大数据类型(string、hash、list、set、zset)(go-redis)

叶子 · · 5382 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前言

使用redis首先要部署redis,载个安装包,部署下即可,本文不赘述了。redis官网:https://redis.io/

接着要下载golang的redis资源包,golang官方推荐的有redisgo和go-reids,个人认为go-redis的封装更加人性化,redisgo的调用是基于命令的,go-redis是基于方法的,所以本文先来介绍go-redis的使用。

2行代码来比较下2种资源包的调用方式:
redisgo: client.Do("SET", "mykey", "我是数据", "EX", "3600")
go-redis:client.Set("mykey", "我是数据", time.Hour)
同样是存储一个1小时后过期的数据,go-redis的调用方式明显更友好。

导入go-redis包

github地址:https://github.com/go-redis/redis
文档地址:https://godoc.org/github.com/go-redis/redis
golang下载资源包相当方便,打开命令行,输入命令:go get -u github.com/go-redis/redis(使用git命令下载资源包,需要先安装git,没安装git的同学可以手动下载后放入src目录下)。

image.png

下载完成会在GOPATH下的src里多了资源包

image.png

导入包:

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

1、链接redis

client := redis.NewClient(&redis.Options{ 
 Addr: "127.0.0.1:6379", 
 Password: "123456", 
 DB: 0, 
}) 
//延迟到程序结束关闭链接
defer client.Close() 
//ping
pong, err := client.Ping().Result() 
if err != nil { 
 fmt.Println("ping error", err.Error()) 
 return 
} 
fmt.Println("ping result:", pong)

解析:
Addr是redis服务的地址,如果部署的reids没有密码,那Password就写"",DB是对应reids 0-15的db
测试redis链接:
pong, err := client.Ping().Result()

2、string 字符串

//string------------------------------------------------------------------------ 
key := "go2key" 
//过期时间1小时 
err = client.Set(key, "我是值", time.Hour).Err() 
if err != nil { 
 fmt.Println("set err", err) 
 return 
} 
 
//获取 
value, err := client.Get(key).Result() 
if err != nil { 
 fmt.Println("Get err", err) 
 return 
} 
fmt.Printf("key:%v 值:%~~~~v \n", key, value)

存储命令:Set,过期时间如果是3分钟则写成 3*timt.Minute
client.Set(key, "我是值", time.Hour)
读取命令:Get
value, err := client.Get(key).Result()

3、struc 结构

//json---------------------------------
//存储结构 
doctor := Doctor{1, "钟南山", 83, 1, time.Now()} 
doctorJson, _ := json.Marshal(doctor) 
client.Set("doctor2", doctorJson, time.Hour) 
 
//读取结构 
doctorResult, _ := client.Get("doctor2").Result() 
var doctor2 Doctor 
//反序列化 
json.Unmarshal([]byte(doctorResult), &doctor2) 
fmt.Println("doctor2", doctor2)

解析:
存储结构其实也是存储string,只是把struc序列化成json,等读取的时候再反序列化成struc
序列化:
doctorJson, _ := json.Marshal(doctor)
反序列化:
json.Unmarshal([]byte(doctorResult), &doctor2)

4、list 列表

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

//list---------------------------------------------------- 
//通道列表 list
listKey := "go2list" 
client.RPush(listKey, "str1", 10, "str2", 15, "str3", 20).Err() 
 
//lpop 取出并移除左边第一个元素 
first, _ := client.LPop(listKey).Result() 
fmt.Printf("列表第一个元素 key:%v value:%v \n", first[0], first[1]) 
 
//Blpop 取出并移除左边第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 
first2, _ := client.BLPop(time.Second*60, listKey).Result() 
fmt.Printf("列表第一个元素 key:%v value:%v \n", first2[0], first2[1]) 
 
//数据长度 
listLen, _ := client.LLen(listKey).Result() 
fmt.Println("list length", listLen) 
 
//获取列表 
listGet, _ := client.LRange(listKey, 1, 2).Result() 
fmt.Println("索引1-2的2个元素元素", listGet)

解析:
存储"str1", 10, "str2", 15, "str3", 20这6个元素到"go2list"中,使用RPush命令往队列右边加入。
从左边取出第一个元素,取出后,这个元素将会从list里移除,这就很像我们的消息队列了。
first, _ := client.LPop(listKey).Result()
BLPop获取左边第一个元素,如果不存在元素,则会一直堵塞,直到time.Second*6060秒内有数据加入,被取出为止。
first2, _ := client.BLPop(time.Second*60, listKey).Result()
获取整个列表数据,这是不会移除数据的
listGet, _ := client.LRange(listKey, 1, 2).Result()
关于list的命令还有很多,例如LPush、Rpop、BRpop、LLen等等

5、hash

hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。可以不用直接获取和更新对象的某个属性。

//hash------------------------------------------- 
hashKey := "userkey_1" 
//set hash 适合存储结构 
client.HSet(hashKey, "name", "叶子") 
client.HSet(hashKey, "age", 18) 
 
//get hash 
hashGet, _ := client.HGet(hashKey, "name").Result() 
fmt.Println("HGet name", hashGet) 
 
//获取所有hash 返回map 
hashGetAll, _ := client.HGetAll(hashKey).Result() 
fmt.Println("HGetAll", hashGetAll)

解析:
存储name属性为叶子,age属性为18的对象到userkey_1中
client.HSet(hashKey, "name", "叶子")
获取某个属性
hashGet, _ := client.HGet(hashKey, "name").Result()
获取userkey_1所有的属性,返回的是一个map对象
hashGetAll, _ := client.HGetAll(hashKey).Result()

6、set 集合

set 是 string 类型的无序集合。

//set-------------------------------------------- 
setKey := "go2set" 
client.SAdd(setKey, "set1") 
client.SAdd(setKey, "set2") 
client.SAdd(setKey, "set3") 
client.SAdd(setKey, "set4") 
 
//获取集合的所有成员 
setList, _ := client.SMembers(setKey).Result() 
fmt.Println("GetSet", setList) 
//移除集合里的set1 
client.SRem(setKey, "set1") 
 
//移除并返回set的一个随机元素 
setFirst, _ := client.SPop(setKey).Result() 
fmt.Println("setFirst", setFirst)

解析:
往集合里添加数据
client.SAdd(setKey, "set1")
获取集合的所有的元素
setList, _ := client.SMembers(setKey).Result()
移除并返回set的一个随机元素,因为set是无序的
setFirst, _ := client.SPop(setKey).Result()

6、zset 有序集合

set是有序的,适合做排行榜业务,我们来模拟一个医生热度排行

//zset------------------------------------------------ 
zsetKey := "go2zset" 
ranking := []*redis.Z{ 
 &redis.Z{Score: 100.0, Member: "钟南山"}, 
 &redis.Z{Score: 80.0, Member: "林医生"}, 
 &redis.Z{Score: 70.0, Member: "王医生"}, 
 &redis.Z{Score: 75.0, Member: "张医生"}, 
 &redis.Z{Score: 59.0, Member: "叶医生"}, 
} 
client.ZAdd(zsetKey, ranking...) 
//golang+5分 
newScore, err := client.ZIncrBy(zsetKey, 5.0, "钟南山").Result() 
fmt.Println("钟南山加5分后的最新分数", newScore) 
//取zset里的前2名热度的医生 
zsetList2, _ := client.ZRevRangeWithScores(zsetKey, 0, 1).Result() 
fmt.Println("zset前2名热度的医生", zsetList2)

解析:
往zset里加入集合数据,数据是[]*redis.Z类型,里面包含ScoreMember2个属性
client.ZAdd(zsetKey, ranking...)
给钟南山加上5分,返回钟南山的最新热度分值
newScore, err := client.ZIncrBy(zsetKey, 5.0, "钟南山").Result()
获取前2名热度的医生,前2名,所以索引是从0到1。
zsetList2, _ := client.ZRevRangeWithScores(zsetKey, 0, 1).Result()

7、设置过期时间

操作string数据的时候,可以在方法里直接传入过期时间。但list、hash、set、zset都没有直接提供相应参数,但redis可以额外设置key的过期时间

//Expire------------------------------------------ 
//设置过期时间 30秒后过期 
client.Expire(hashKey, time.Second*30) 
client.ExpireAt(hashKey, time.Now().Add(time.Second*30)) 
//删除key 
//client.Del("go2key", "go2list") 
 
//ttl 获取key的生存时间 
duration, err := client.TTL(key).Result() 
if err != nil { 
 fmt.Println("TTL err", err) 
 return 
} 
fmt.Printf("key%v的有效时间,%v,%v \n", key, duration.String(), duration.Seconds())

完整demo

package main
import (
 "encoding/json"
 "fmt"
 "github.com/go-redis/redis"
 "time"
)
type Doctor struct { 
 ID int64 
 Name string 
 Age int 
 Sex int 
 AddTime time.Time 
}
func main() {
 client := redis.NewClient(&redis.Options{
 Addr: "127.0.0.1:6379",
 Password: "123456",
 DB: 0,
 })
 //延迟到程序结束关闭链接
 defer client.Close()
 //ping
 pong, err := client.Ping().Result()
 if err != nil {
 fmt.Println("ping error", err.Error())
 return
 }
 fmt.Println("ping result:", pong)
 //string------------------------------------------------------------------------
 key := "go2key"
 //过期时间1小时
 err = client.Set(key, "我是值", time.Hour).Err()
 if err != nil {
 fmt.Println("set err", err)
 return
 }
 //获取
 value, err := client.Get(key).Result()
 if err != nil {
 fmt.Println("Get err", err)
 return
 }
 fmt.Printf("key:%v 值:%v \n", key, value)
 //list------------------------------------------------------------------------
 //通道列表 list
 listKey := "go2list"
 client.RPush(listKey, "str1", 10, "str2", 15, "str3", 20).Err()
 //lpop 取出并移除左边第一个元素
 first, _ := client.LPop(listKey).Result()
 fmt.Printf("列表第一个元素 key:%v value:%v \n", first[0], first[1])
 //Blpop 取出并移除左边第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
 first2, _ := client.BLPop(time.Second*60, listKey).Result()
 fmt.Printf("列表第一个元素 key:%v value:%v \n", first2[0], first2[1])
 //数据长度
 listLen, _ := client.LLen(listKey).Result()
 fmt.Println("list length", listLen)
 //获取列表
 listGet, _ := client.LRange(listKey, 1, 2).Result()
 fmt.Println("索引1-2的2个元素元素", listGet)
 //json------------------------------------------------------------------------
 //存储结构
 doctor := Doctor{1, "钟南山", 83, 1, time.Now()}
 doctorJson, _ := json.Marshal(doctor)
 client.Set("doctor2", doctorJson, time.Hour)
 //读取结构
 doctorResult, _ := client.Get("doctor2").Result()
 var doctor2 Doctor
 //反序列化
 json.Unmarshal([]byte(doctorResult), &doctor2)
 fmt.Println("doctor2", doctor2)
 //hash------------------------------------------------------------------------
 hashKey := "gohash"
 //set hash 适合存储结构
 client.HSet(hashKey, "name", "叶子")
 client.HSet(hashKey, "age", 18)
 //get hash
 hashGet, _ := client.HGet(hashKey, "name").Result()
 fmt.Println("HGet name", hashGet)
 //获取所有hash 返回map
 hashGetAll, _ := client.HGetAll(hashKey).Result()
 fmt.Println("HGetAll", hashGetAll)
 //set------------------------------------------------------------------------
 setKey := "go2set"
 client.SAdd(setKey, "set1")
 client.SAdd(setKey, "set2")
 client.SAdd(setKey, "set3")
 client.SAdd(setKey, "set4")
 //获取集合的所有成员
 setList, _ := client.SMembers(setKey).Result()
 fmt.Println("GetSet", setList)
 //移除集合里的set1
 client.SRem(setKey, "set1")
 //移除并返回set的一个随机元素
 setFirst, _ := client.SPop(setKey).Result()
 fmt.Println("set的随机元素", setFirst)
 //zset------------------------------------------------------------------------
 zsetKey := "go2zset"
 ranking := []*redis.Z{
 &redis.Z{Score: 100.0, Member: "钟南山"},
 &redis.Z{Score: 80.0, Member: "林医生"},
 &redis.Z{Score: 70.0, Member: "王医生"},
 &redis.Z{Score: 75.0, Member: "张医生"},
 &redis.Z{Score: 59.0, Member: "叶医生"},
 }
 client.ZAdd(zsetKey, ranking...)
 //golang+5分
 newScore, err := client.ZIncrBy(zsetKey, 5.0, "钟南山").Result()
 fmt.Println("钟南山加5分后的最新分数", newScore)
 //取zset里的前2名热度的医生
 zsetList2, _ := client.ZRevRangeWithScores(zsetKey, 0, 1).Result()
 fmt.Println("zset前2名热度的医生", zsetList2)
 //Expire------------------------------------------------------------------------
 //设置过期时间 30秒后过期
 client.Expire(hashKey, time.Second*30)
 client.ExpireAt(hashKey, time.Now().Add(time.Second*30))
 //删除key
 //client.Del("go2key", "go2list")
 //ttl 获取key的生存时间
 duration, err := client.TTL(key).Result()
 if err != nil {
 fmt.Println("TTL err", err)
 return
 }
 fmt.Printf("key%v的有效时间,%v,%v \n", key, duration.String(), duration.Seconds())
}

总结

以上就是redis常用的方法示例,go-redis的封装非常的友好,所有的方法名与redis自己的命令都是相对应的,非常易于理解,即便不看文档,只要你熟悉redis命令,使用起来也是很顺畅的。


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
5382 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏