8.2 Go与各种Redis数据类型
8.2.1 读写列表类对象
工程结构如下:
(base) yanglei@yuanhong redisDataType % tree ./
./
├── conn
│ ├── pool.go
│ └── redis.go
├── dataType
│ └── list
│ └── list.go
├── go.mod
├── go.sum
└── main.go
3 directories, 6 files
其中conn/
目录下的文件和上一小节的完全相同.
dataType/list/list.go
:
package list
import (
"github.com/gomodule/redigo/redis"
)
func LPush(conn redis.Conn, key string, values ...string) (int, error) {
length := 0
for _, value := range values {
err := conn.Send("LPUSH", key, value)
if err != nil {
return 0, err
}
}
err := conn.Flush()
if err != nil {
return 0, err
}
for i := 0; i < len(values); i++ {
reply, _ := redis.Int(conn.Receive())
length = reply
}
return length, nil
}
func RPush(conn redis.Conn, key string, values ...string) (int, error) {
length := 0
for _, value := range values {
err := conn.Send("RPUSH", key, value)
if err != nil {
return 0, err
}
}
err := conn.Flush()
if err != nil {
return 0, err
}
for i := 0; i < len(values); i++ {
reply, _ := redis.Int(conn.Receive())
length = reply
}
return length, nil
}
func LPop(conn redis.Conn, key string) (string, error) {
return redis.String(conn.Do("LPOP", key))
}
func RPop(conn redis.Conn, key string) (string, error) {
return redis.String(conn.Do("RPOP", key))
}
func LLen(conn redis.Conn, key string) (int, error) {
return redis.Int(conn.Do("LLEN", key))
}
func LRange(conn redis.Conn, key string, start int, end int) ([]string, error) {
return redis.Strings(conn.Do("LRANGE", key, start, end))
}
func LTrim(conn redis.Conn, key string, start int, end int) (string, error) {
return redis.String(conn.Do("LTRIM", key, start, end))
}
func LSet(conn redis.Conn, key string, index int, value string) (string, error) {
return redis.String(conn.Do("LSET", key, index, value))
}
func LIndex(conn redis.Conn, key string, index int) (string, error) {
return redis.String(conn.Do("LINDEX", key, index))
}
main.go
:
package main
import (
"fmt"
"log"
"redisDataType/conn"
"redisDataType/dataType/list"
"time"
)
func main() {
conf := conn.Conf{
NetWork: "tcp",
Address: "localhost:6379",
User: "redis_user",
Password: "redis_password",
}
poolConf := conn.PoolConf{
MaxIdle: 10,
MaxActive: 100,
IdleTimeout: time.Hour,
Conf: conf,
}
// 初始化连接池
conn.NewPool(poolConf)
// 从连接池中获取一个连接
redisConn, err := conn.GetConnFromPool(poolConf)
if err != nil {
log.Fatalf("get conn from pool error: %v\n", err)
}
// 将该连接返回到连接池中
defer conn.CloseConnToPool(redisConn)
// 用LPUSH命令将元素插入到列表头部
values := []string{"3", "2", "1"}
length, err := list.LPush(redisConn, "myList", values...)
if err != nil {
log.Fatalf("LPUSH error: %v\n", err)
}
fmt.Printf("after LPUSH, length of list = %d\n", length)
// 查看列表中的元素
elements, err := list.LRange(redisConn, "myList", 0, -1)
if err != nil {
log.Fatalf("LRANGE error: %v\n", err)
}
fmt.Printf("after LPUSH, LRANGE: %v\n", elements)
// 用RPUSH命令将元素插入到列表尾部
values = []string{"4", "5", "6"}
length, err = list.RPush(redisConn, "myList", values...)
if err != nil {
log.Fatalf("RPUSH error: %v\n", err)
}
fmt.Printf("after RPUSH, length of list = %d\n", length)
// 查看列表中的元素
elements, err = list.LRange(redisConn, "myList", 0, -1)
if err != nil {
log.Fatalf("LRANGE error: %v\n", err)
}
fmt.Printf("after RPUSH, LRANGE: %v\n", elements)
// 用LPOP命令从列表头部弹出一个元素
element, err := list.LPop(redisConn, "myList")
if err != nil {
log.Fatalf("LPOP error: %v\n", err)
}
fmt.Printf("the element which operated by LPOP = %s\n", element)
// 查看列表中的元素
elements, err = list.LRange(redisConn, "myList", 0, -1)
if err != nil {
log.Fatalf("LRANGE error: %v\n", err)
}
fmt.Printf("after LPOP, LRANGE: %v\n", elements)
}
运行结果如下:
(base) yanglei@yuanhong redisDataType % go run main.go
after LPUSH, length of list = 3
after LPUSH, LRANGE: [1 2 3]
after RPUSH, length of list = 6
after RPUSH, LRANGE: [1 2 3 4 5 6]
the element which operated by LPOP = 1
after LPOP, LRANGE: [2 3 4 5 6]
8.2.2 读写哈希表类对象
工程结构如下:
(base) yanglei@yuanhong redisDataType % tree ./
./
├── conn
│ ├── pool.go
│ └── redis.go
├── dataType
│ ├── hash
│ │ └── hash.go
│ └── list
│ └── list.go
├── go.mod
├── go.sum
└── main.go
4 directories, 7 files
dataType/hash/hash.go
:
package hash
import (
"github.com/gomodule/redigo/redis"
)
func HSet(conn redis.Conn, key string, hashes map[string]string) (int, error) {
_, err := conn.Do("HMSET", redis.Args{}.Add(key).AddFlat(hashes)...)
if err != nil {
return 0, err
}
length, err := HLen(conn, key)
if err != nil {
// TODO: 此处获取长度失败不应该返回0
return 0, err
}
return length, nil
}
func HLen(conn redis.Conn, key string) (int, error) {
return redis.Int(conn.Do("HLEN", key))
}
func HGet(conn redis.Conn, key string, field string) (string, error) {
return redis.String(conn.Do("HGET", key, field))
}
func HGetAll(conn redis.Conn, key string) (map[string]string, error) {
return redis.StringMap(conn.Do("HGETALL", key))
}
func HExists(conn redis.Conn, key string, field string) (bool, error) {
return redis.Bool(conn.Do("HEXISTS", key, field))
}
func HDel(conn redis.Conn, key string, fields ...string) (int, error) {
args := redis.Args{}.Add(key).AddFlat(fields)
return redis.Int(conn.Do("HDEL", args...))
}
main.go
:
package main
import (
"fmt"
"log"
"redisDataType/conn"
"redisDataType/dataType/hash"
"time"
)
func main() {
conf := conn.Conf{
NetWork: "tcp",
Address: "localhost:6379",
User: "redis_user",
Password: "redis_password",
}
poolConf := conn.PoolConf{
MaxIdle: 10,
MaxActive: 100,
IdleTimeout: time.Hour,
Conf: conf,
}
// 初始化连接池
conn.NewPool(poolConf)
// 从连接池中获取一个连接
redisConn, err := conn.GetConnFromPool(poolConf)
if err != nil {
log.Fatalf("get conn from pool error: %v\n", err)
}
// 将该连接返回到连接池中
defer conn.CloseConnToPool(redisConn)
// 向哈希表添加字段
hashMap := map[string]string{
"field1": "value1",
"field2": "value2",
}
length, err := hash.HSet(redisConn, "hash", hashMap)
if err != nil {
log.Fatalf("HSET error: %v\n", err)
}
fmt.Printf("after HSET, the length of hash is %d\n", length)
// 从哈希表中获取字段
value, err := hash.HGet(redisConn, "hash", "field1")
if err != nil {
log.Fatalf("HGET error: %v\n", err)
}
fmt.Printf("key = %s, field = %s, value = %s \n", "hash", "field1", value)
// 获取哈希表的长度
length, err = hash.HLen(redisConn, "hash")
if err != nil {
log.Fatalf("HLEN error: %v\n", err)
}
fmt.Printf("the length of hash is %d\n", length)
// 获取哈希表的所有字段和值
hashMapResult, err := hash.HGetAll(redisConn, "hash")
if err != nil {
log.Fatalf("HGETALL error: %v\n", err)
}
fmt.Printf("the result of HGETALL is %v\n", hashMapResult)
// 判断哈希表中是否存在某个字段
exists, err := hash.HExists(redisConn, "hash", "field1")
if err != nil {
log.Fatalf("HEXISTS error: %v\n", err)
}
fmt.Printf("the field1 of hash exists: %v\n", exists)
exists, err = hash.HExists(redisConn, "hash", "field3")
if err != nil {
log.Fatalf("HEXISTS error: %v\n", err)
}
fmt.Printf("the field3 of hash exists: %v\n", exists)
// 删除哈希表中的字段
deletedNum, err := hash.HDel(redisConn, "hash", "field1", "field2", "field3")
if err != nil {
log.Fatalf("HDEL error: %v\n", err)
}
fmt.Printf("the number of deleted fields is %d\n", deletedNum)
}
(base) yanglei@yuanhong redisDataType % go run main.go
after HSET, the length of hashes is 2
key = hashes, field = field1, value = value1
the length of hashes is 2
the result of HGETALL is map[field1:value1 field2:value2]
the field1 of hashes exists: true
the field3 of hashes exists: false
the number of deleted fields is 2
8.2.3 读写集合类对象
工程结构如下:
(base) yanglei@yuanhong redisDataType % tree ./
./
├── conn
│ ├── pool.go
│ └── redis.go
├── dataType
│ ├── hash
│ │ └── hash.go
│ ├── list
│ │ └── list.go
│ └── set
│ └── set.go
├── go.mod
├── go.sum
└── main.go
5 directories, 8 files
dataType/set/set.go
:
package set
import "github.com/gomodule/redigo/redis"
func SAdd(conn redis.Conn, key string, members ...interface{}) (int, error) {
args := redis.Args{}.Add(key).AddFlat(members)
return redis.Int(conn.Do("SADD", args...))
}
func SIsMember(conn redis.Conn, key string, member interface{}) (bool, error) {
return redis.Bool(conn.Do("SISMEMBER", key, member))
}
func SMembers(conn redis.Conn, key string) ([]string, error) {
return redis.Strings(conn.Do("SMEMBERS", key))
}
// SRem 删除集合中的元素(根据给定的元素值删除) 返回删除的元素个数
func SRem(conn redis.Conn, key string, members ...interface{}) (int, error) {
args := redis.Args{}.Add(key).AddFlat(members)
return redis.Int(conn.Do("SREM", args...))
}
// SPop 随机删除并返回集合中的一个元素
func SPop(conn redis.Conn, key string) (string, error) {
return redis.String(conn.Do("SPOP", key))
}
main.go
:
package main
import (
"fmt"
"log"
"redisDataType/conn"
"redisDataType/dataType/set"
"time"
)
func main() {
conf := conn.Conf{
NetWork: "tcp",
Address: "localhost:6379",
User: "redis_user",
Password: "redis_password",
}
poolConf := conn.PoolConf{
MaxIdle: 10,
MaxActive: 100,
IdleTimeout: time.Hour,
Conf: conf,
}
// 初始化连接池
conn.NewPool(poolConf)
// 从连接池中获取一个连接
redisConn, err := conn.GetConnFromPool(poolConf)
if err != nil {
log.Fatalf("get conn from pool error: %v\n", err)
}
// 将该连接返回到连接池中
defer conn.CloseConnToPool(redisConn)
// 向集合中添加元素
newMemberNum, err := set.SAdd(redisConn, "setKey", "setValue1", "setValue2", "setValue4", "setValue6")
if err != nil {
log.Fatalf("SADD error: %v\n", err)
}
fmt.Printf("new memeber num: %d\n", newMemberNum)
newMemberNum, err = set.SAdd(redisConn, "setKey", "setValue2", "setValue3")
if err != nil {
log.Fatalf("SADD error: %v\n", err)
}
fmt.Printf("new memeber num: %d\n", newMemberNum)
// 判断给定元素是否存在于集合中
isMember, err := set.SIsMember(redisConn, "setKey", "setValue1")
if err != nil {
log.Fatalf("SISMEMBER error: %v\n", err)
}
fmt.Printf("setValue1 is member: %v\n", isMember)
isMember, err = set.SIsMember(redisConn, "setKey", "setValue5")
if err != nil {
log.Fatalf("SISMEMBER error: %v\n", err)
}
fmt.Printf("setValue5 is member: %v\n", isMember)
// 获取集合的所有元素
members, err := set.SMembers(redisConn, "setKey")
if err != nil {
log.Fatalf("SMEMBERS error: %v\n", err)
}
fmt.Printf("members: %v\n", members)
// 根据给定的元素值删除元素
delSets := []interface{}{"setValue1", "setValue2", "setValue5"}
delNum, err := set.SRem(redisConn, "setKey", delSets...)
if err != nil {
log.Fatalf("SREM error: %v\n", err)
}
fmt.Printf("delete num by SREM: %d\n", delNum)
// 随机删除并返回集合中的一个元素
popMember, err := set.SPop(redisConn, "setKey")
if err != nil {
log.Fatalf("SPOP error: %v\n", err)
}
fmt.Printf("pop member: %s\n", popMember)
}
运行结果如下:
(base) yanglei@yuanhong redisDataType % go run main.go
new memeber num: 4
new memeber num: 1
setValue1 is member: true
setValue5 is member: false
members: [setValue2 setValue4 setValue1 setValue6 setValue3]
delete num by SREM: 2
pop member: setValue4
8.2.4 读写有序集合类对象
工程结构如下:
(base) yanglei@yuanhong redisDataType % tree ./
./
├── conn
│ ├── pool.go
│ └── redis.go
├── dataType
│ ├── hash
│ │ └── hash.go
│ ├── list
│ │ └── list.go
│ ├── set
│ │ └── set.go
│ └── sortedSet
│ └── sortedSet.go
├── go.mod
├── go.sum
└── main.go
6 directories, 9 files
dataType/sortedSet/sortedSet.go
:
package sortedSet
import (
"github.com/gomodule/redigo/redis"
)
func ZAdd(conn redis.Conn, key string, scoreMap map[int]interface{}) (int, error) {
args := redis.Args{}.Add(key).AddFlat(scoreMap)
return redis.Int(conn.Do("ZADD", args...))
}
func ZCard(conn redis.Conn, key string) (int, error) {
return redis.Int(conn.Do("ZCARD", key))
}
// ZRange 根据索引获取有序集合中的元素(按照分数从小到大排序)
func ZRange(conn redis.Conn, key string, start int, stop int) ([]string, error) {
return redis.Strings(conn.Do("ZRANGE", key, start, stop))
}
// ZRevRange 根据索引获取有序集合中的元素(按照分数从大到小排序)
func ZRevRange(conn redis.Conn, key string, start int, stop int) ([]string, error) {
return redis.Strings(conn.Do("ZREVRANGE", key, start, stop))
}
func ZScore(conn redis.Conn, key string, member string) (float64, error) {
return redis.Float64(conn.Do("ZSCORE", key, member))
}
func ZRem(conn redis.Conn, key string, members ...string) (int, error) {
args := redis.Args{}.Add(key).AddFlat(members)
return redis.Int(conn.Do("ZREM", args...))
}
main.go
:
package main
import (
"fmt"
"log"
"redisDataType/conn"
"redisDataType/dataType/sortedSet"
"time"
)
func main() {
conf := conn.Conf{
NetWork: "tcp",
Address: "localhost:6379",
User: "redis_user",
Password: "redis_password",
}
poolConf := conn.PoolConf{
MaxIdle: 10,
MaxActive: 100,
IdleTimeout: time.Hour,
Conf: conf,
}
// 初始化连接池
conn.NewPool(poolConf)
// 从连接池中获取一个连接
redisConn, err := conn.GetConnFromPool(poolConf)
if err != nil {
log.Fatalf("get conn from pool error: %v\n", err)
}
// 将该连接返回到连接池中
defer conn.CloseConnToPool(redisConn)
// 添加元素到有序集合中
scoreMap := map[int]interface{}{
1: "one",
3: "three",
}
addNum, err := sortedSet.ZAdd(redisConn, "myZSet", scoreMap)
if err != nil {
log.Fatalf("ZADD error: %v\n", err)
}
fmt.Printf("addNum: %d\n", addNum)
scoreMap = map[int]interface{}{
3: "three",
5: "five",
}
addNum, err = sortedSet.ZAdd(redisConn, "myZSet", scoreMap)
if err != nil {
log.Fatalf("ZADD error: %v\n", err)
}
fmt.Printf("addNum: %d\n", addNum)
// 获取有序集合中的元素数量
cardNum, err := sortedSet.ZCard(redisConn, "myZSet")
if err != nil {
log.Fatalf("ZCARD error: %v\n", err)
}
fmt.Printf("cardNum: %d\n", cardNum)
// 根据分数的索引获取元素
// 按分数从小到大排序
members, err := sortedSet.ZRange(redisConn, "myZSet", 0, 1)
if err != nil {
log.Fatalf("ZRANGE error: %v\n", err)
}
fmt.Printf("ZRANGE members: %v\n", members)
// 按分数从大到小排序
members, err = sortedSet.ZRevRange(redisConn, "myZSet", 0, 1)
if err != nil {
log.Fatalf("ZREVRANGE error: %v\n", err)
}
fmt.Printf("ZREVRANGE members: %v\n", members)
// 获取指定成员的分数
score, err := sortedSet.ZScore(redisConn, "myZSet", "three")
if err != nil {
log.Fatalf("ZSCORE error: %v\n", err)
}
fmt.Printf("ZSCORE score: %.1f\n", score)
// 删除指定成员
deletedMembers := []string{"three", "five", "seven"}
delNum, err := sortedSet.ZRem(redisConn, "myZSet", deletedMembers...)
if err != nil {
log.Fatalf("ZREM error: %v\n", err)
}
fmt.Printf("ZREM delNum: %d\n", delNum)
}
运行结果:
(base) yanglei@yuanhong redisDataType % go run main.go
addNum: 2
addNum: 1
cardNum: 3
ZRANGE members: [one three]
ZREVRANGE members: [five three]
ZSCORE score: 3.0
ZREM delNum: 2
8.2.5 操作地理位置数据
Last updated