使用Redigo (2) 处理各种数据类型
首先
我们来看一下Redis的Go语言客户端库Redigo的使用方法。本文介绍了各种数据类型的处理方式。
Redis有以下五种数据类型。
-
- 文字列型
-
- リスト型
-
- セット型
-
- ソート済みセット型
- ハッシュ型
在(1)的文章中,我已经了解了有关字符串类型的信息。在本文中,我们将探讨Redigo的基本用法,并介绍其他四种类型。
环境
-
- OS: Windows 10
-
- Redis: win-3.2.100
Go言語: 1.11
列表类型
列表类型是指字符串类型的双向列表。命令列表请参考参考资料。首先进行简单的元素添加和获取操作。
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
// 接続
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
panic(err)
}
defer conn.Close()
// 要素の追加
_, err = conn.Do("RPUSH", "seasons", "spring")
_, err = conn.Do("RPUSH", "seasons", "summer")
_, err = conn.Do("RPUSH", "seasons", "autumn")
_, err = conn.Do("RPUSH", "seasons", "winter")
// 要素の取得
a, err := redis.String(conn.Do("LINDEX", "seasons", 2))
if err != nil {
panic(err)
}
fmt.Println(a) // autumn
// 全体の取得
s, err := redis.Strings(conn.Do("LRANGE", "seasons", 0, -1))
if err != nil {
panic(err)
}
fmt.Println(s) // [spring summer autumn winter]
}
RPUSH是一个命令,用于将元素添加到列表的末尾(这里省略了返回值检查)。我们正在向名为”seasons”的键的列表中添加了四个元素。
LINDEX是一个命令,用于返回列表中由索引指定的元素。
LRANGE是一个命令,用于返回列表中由两个索引指定范围内的元素。”0″表示起始位置,”-1″表示末尾位置(即返回所有元素)。我们还将结果传递给redis.Strings。这是一个将conn.Do的结果转换为[]string的实用函数。
要素的删除可以按照以下方式进行。
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
// 接続
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
panic(err)
}
defer conn.Close()
// 要素の追加
_, err = conn.Do("RPUSH", "words", "xxxxxx")
_, err = conn.Do("RPUSH", "words", "yyy")
_, err = conn.Do("RPUSH", "words", "z")
_, err = conn.Do("RPUSH", "words", "xxxxxx")
// 要素の削除(先頭に近いxxxxxxを1個だけ消す)
n, err := redis.Int(conn.Do("LREM", "words", 1, "xxxxxx"))
if err != nil {
panic(err)
}
fmt.Println(n) // 1
// 要素の削除(先頭の要素を消す)
a, err := redis.String(conn.Do("LPOP", "words"))
if err != nil {
panic(err)
}
fmt.Println(a) // yyy
// 全体の取得
s, err := redis.Strings(conn.Do("LRANGE", "words", 0, -1))
if err != nil {
panic(err)
}
fmt.Println(s) // [z xxxxxx]
}
在将四个字符串添加到名为words的键列表之后,使用LREM和LPOP进行元素删除。
LREM命令会从列表头开始查找并删除指定值的指定数量的元素。在此情况下,将删除最先添加的xxxxxx元素。返回值为已删除的元素数量。通过redis.Int将结果转换为Go语言的int类型。
LPOP函数用于删除列表的首个元素。在此操作后,列表的状态变为[yyy, z, xxxxxx],因此首个元素yyy被删除。函数返回被删除的元素。我们将其传递给redis.String,然后将其转换为Go中的string类型。
这次我没有介绍,但是列表类型的命令还有其他的选项,比如LTRIM可以从开头和末尾截取元素,LSET可以修改特定元素的值,RPOPLPUSH可以在两个列表之间移动元素。
套装类型
集合类型是一种字符串类型的集合。与列表类型不同,集合类型不允许有重复的元素。请参考参考资料中的命令列表。以下展示了一系列关于添加、删除和获取元素的操作流程。
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
// 接続
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
panic(err)
}
defer conn.Close()
// 要素の追加
_, err = conn.Do("SADD", "numbers", "one")
_, err = conn.Do("SADD", "numbers", "two")
_, err = conn.Do("SADD", "numbers", "three")
_, err = conn.Do("SADD", "numbers", "four")
// 要素の追加(既に追加済み)
n, err := redis.Int(conn.Do("SADD", "numbers", "one"))
if err != nil {
panic(err)
}
fmt.Println(n) // 0
// 要素の削除
m, err := redis.Int(conn.Do("SREM", "numbers", "three"))
if err != nil {
panic(err)
}
fmt.Println(m) // 1
// 要素の存在確認
k, err := redis.Int(conn.Do("SISMEMBER", "numbers", "five"))
if err != nil {
panic(err)
}
fmt.Println(k) // 0
// 全体の取得
s, err := redis.Strings(conn.Do("SMEMBERS", "numbers"))
if err != nil {
panic(err)
}
fmt.Println(s) // [one two four]
}
SADD会向集合中添加元素。如果尝试重新添加已经存在的元素,则返回值将为0(成功时返回1)。
SREM会从集合中返回指定的元素。
SISMEMBER会返回指定的元素是否存在于集合中。如果存在则返回1,否则返回0。
SMEMBERS会获取集合中的所有元素。
关于集合命令,除了还有随机删除元素的SPOP命令(什么时候用呢?),获取元素个数的SCARD命令,以及在两个集合之间移动元素的SMOVE命令等。此外,还有多个集合的交集(SINTER)和并集(SUNION),以及差集(SDIFF)等集合运算相关的命令都很丰富。
已排序的集合类型
已排序的集合是根据分数进行排序的字符串集合。我认为它类似于C++中的std::multimap<float,string>类型。请参考命令列表。以下是以5名学生的考试成绩为主题的常见操作示例。
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
// 接続
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
panic(err)
}
defer conn.Close()
// 要素の追加
_, err = conn.Do("ZADD", "math_test", 60, "alice")
_, err = conn.Do("ZADD", "math_test", 50, "bob")
_, err = conn.Do("ZADD", "math_test", 100, "charlie")
_, err = conn.Do("ZADD", "math_test", 10, "dave")
_, err = conn.Do("ZADD", "math_test", 20, "eve")
// 最低スコアの要素(とそのスコア)を得る
s, err := redis.Strings(conn.Do("ZRANGE", "math_test", 0, 0, "WITHSCORES"))
if err != nil {
panic(err)
}
fmt.Println(s) // [dave 10]
// スコア40以上70以下の要素(とそのスコア)を得る
t, err := redis.Strings(conn.Do("ZRANGEBYSCORE", "math_test", 40, 70, "WITHSCORES"))
if err != nil {
panic(err)
}
fmt.Println(t) // [bob 50 alice 60]
// スコアが小さい順に要素を2個削除する
n, err := redis.Int(conn.Do("ZREMRANGEBYRANK", "math_test", 0, 1))
if err != nil {
panic(err)
}
fmt.Println(n) // 2
// 全体の取得
u, err := redis.Strings(conn.Do("ZREVRANGE", "math_test", 0, -1))
if err != nil {
panic(err)
}
fmt.Println(u) // [charlie alice bob]
}
元素将以点数从低到高的顺序进行排序并保持。
如果要获取特定排名的学生,可以使用ZRANGE。例如,当指定ZRANGE 0, 0时,将获得排名在0或更高且排名在0或更低的学生,也就是最低分的学生(以0索引)。如果指定WITHSCORES选项,还可以同时获取分数。相反,如果想获取最高分的学生,可以使用ZREVRANGE。
当根据分数范围筛选时,可以使用ZRANGEBYSCORE。例如,当指定ZRANGEBYSCORE 40, 70时,将获得分数在40或更高且分数在70或更低的元素。
要删除元素,可以使用ZREMRANGEBYRANK。ZREMRANGEBYRANK 0, 1表示删除排名在0或更高且排名在1或更低的学生,也就是删除dave和eve。
哈希类型
哈希类型是一个映射字符串类型的对(字段和值)。我认为它类似于Python的字典类型(值仅限于字符串)。请参考命令列表以获取更多信息。以下是一个示例,展示了如何向名为profile的键添加或更新字段和值的对。
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
// 接続
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
panic(err)
}
defer conn.Close()
// 要素の追加
_, err = conn.Do("HSET", "profile", "name", "yamada")
_, err = conn.Do("HSET", "profile", "age", "30")
_, err = conn.Do("HSET", "profile", "country", "america")
// 要素の追加と更新
t, err := redis.String(conn.Do("HMSET", "profile", "country", "japan", "city", "tokyo"))
if err != nil {
panic(err)
}
fmt.Println(t) // OK
// 要素の取得
s, err := redis.String(conn.Do("HGET", "profile", "country"))
if err != nil {
panic(err)
}
fmt.Println(s) // japan
// 値をインクリメントする
n, err := redis.Int(conn.Do("HINCRBY", "profile", "age", "2"))
if err != nil {
panic(err)
}
fmt.Println(n) // 32
// 全体の取得
u, err := redis.Strings(conn.Do("HGETALL", "profile"))
if err != nil {
panic(err)
}
fmt.Println(u) // [name yamada age 32 country japan city tokyo]
}
使用HSET来添加字段和值。在这里,我们丢弃了返回值,但如果字段已经存在,则返回0(值将被覆盖),如果不存在,则返回1。
您也可以使用HMSET添加多对字段和值。您可以交替列出字段1、值1、字段2、值2等。
您还可以使用HINCRBY来增加或减少值。值必须在64位带符号整数范围内。
您还可以使用HGETALL来获取所有的字段和值,它们会交替出现。
最后
我们将在Redigo中看到如何处理Redis的各种数据类型。
请参考
-
- Redigoを使う(1) 基本的な使い方
-
- Redigoを使う(3) トランザクションを行う
-
- Redigoを使う(4) コネクションプールを使う
-
- Redigoを使う(5) ユーティリティ関数
- Redigoを使う(6) パブリッシュ/サブスクライブ