go+redis
go语言操作redis
有个包,一个是 go-redis
,另一个是redigo
,官方推荐第二种,但是个人比较喜欢用第一种。
# 连接数据库
package main
import (
"fmt"
"log"
"math/rand"
"sync"
"time"
"github.com/go-redis/redis"
)
var redisdb *redis.Client
var wg sync.WaitGroup
func main() {
wg.Add(1)
go testRedisBase()
wg.Wait()
}
func testRedisBase() {
defer wg.Done()
//连接服务器
redisdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379", // use default Addr
Password: "", // no password set
DB: 0, // use default DB
})
//心跳
pong, err := redisdb.Ping().Result()
log.Println(pong, err) // Output: PONG <nil>
ExampleClient_String()
ExampleClient_List()
ExampleClient_Hash()
ExampleClient_Set()
ExampleClient_SortSet()
ExampleClient_HyperLogLog()
ExampleClient_CMD()
ExampleClient_Scan()
ExampleClient_Tx()
ExampleClient_Script()
ExampleClient_PubSub()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 操作String格式
func ExampleClient_String() {
log.Println("ExampleClient_String")
defer log.Println("ExampleClient_String")
//kv读写
err := redisdb.Set("key", "value", 1*time.Second).Err()
log.Println(err)
//获取过期时间
tm, err := redisdb.TTL("key").Result()
log.Println(tm)
val, err := redisdb.Get("key").Result()
log.Println(val, err)
val2, err := redisdb.Get("missing_key").Result()
if err == redis.Nil {
log.Println("missing_key does not exist")
} else if err != nil {
log.Println("missing_key", val2, err)
}
//不存在才设置 过期时间 nx ex
value, err := redisdb.SetNX("counter", 0, 1*time.Second).Result()
log.Println("setnx", value, err)
//Incr
result, err := redisdb.Incr("counter").Result()
log.Println("Incr", result, err)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 操作 List 格式
func ExampleClient_List() {
log.Println("ExampleClient_List")
defer log.Println("ExampleClient_List")
//添加
log.Println(redisdb.RPush("list_test", "message1").Err())
log.Println(redisdb.RPush("list_test", "message2").Err())
//设置
log.Println(redisdb.LSet("list_test", 2, "message set").Err())
//remove
ret, err := redisdb.LRem("list_test", 3, "message1").Result()
log.Println(ret, err)
rLen, err := redisdb.LLen("list_test").Result()
log.Println(rLen, err)
//遍历
lists, err := redisdb.LRange("list_test", 0, rLen-1).Result()
log.Println("LRange", lists, err)
//pop没有时阻塞
result, err := redisdb.BLPop(1*time.Second, "list_test").Result()
log.Println("result:", result, err, len(result))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 操作 Hash 格式
func ExampleClient_Hash() {
log.Println("ExampleClient_Hash")
defer log.Println("ExampleClient_Hash")
datas := map[string]interface{}{
"name": "LI LEI",
"sex": 1,
"age": 28,
"tel": 123445578,
}
//添加
if err := redisdb.HMSet("hash_test", datas).Err(); err != nil {
log.Fatal(err)
}
//获取
rets, err := redisdb.HMGet("hash_test", "name", "sex").Result()
log.Println("rets:", rets, err)
//成员
retAll, err := redisdb.HGetAll("hash_test").Result()
log.Println("retAll", retAll, err)
//存在
bExist, err := redisdb.HExists("hash_test", "tel").Result()
log.Println(bExist, err)
bRet, err := redisdb.HSetNX("hash_test", "id", 100).Result()
log.Println(bRet, err)
//删除
log.Println(redisdb.HDel("hash_test", "age").Result())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 操作 Set 格式(无序无重复)
func ExampleClient_Set() {
log.Println("ExampleClient_Set")
defer log.Println("ExampleClient_Set")
//添加
ret, err := redisdb.SAdd("set_test", "11", "22", "33", "44").Result()
log.Println(ret, err)
//数量
count, err := redisdb.SCard("set_test").Result()
log.Println(count, err)
//删除
ret, err = redisdb.SRem("set_test", "11", "22").Result()
log.Println(ret, err)
//成员
members, err := redisdb.SMembers("set_test").Result()
log.Println(members, err)
//查看是否是成员
bret, err := redisdb.SIsMember("set_test", "33").Result()
log.Println(bret, err)
redisdb.SAdd("set_a", "11", "22", "33", "44")
redisdb.SAdd("set_b", "11", "22", "33", "55", "66", "77")
//差集
diff, err := redisdb.SDiff("set_a", "set_b").Result()
log.Println(diff, err)
//交集
inter, err := redisdb.SInter("set_a", "set_b").Result()
log.Println(inter, err)
//并集
union, err := redisdb.SUnion("set_a", "set_b").Result()
log.Println(union, err)
ret, err = redisdb.SDiffStore("set_diff", "set_a", "set_b").Result()
log.Println(ret, err)
rets, err := redisdb.SMembers("set_diff").Result()
log.Println(rets, err)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 操作 zset 格式
func ExampleClient_SortSet() {
log.Println("ExampleClient_SortSet")
defer log.Println("ExampleClient_SortSet")
addArgs := make([]redis.Z, 100)
for i := 1; i < 100; i++ {
addArgs = append(addArgs, redis.Z{Score: float64(i), Member: fmt.Sprintf("a_%d", i)})
}
//log.Println(addArgs)
Shuffle := func(slice []redis.Z) {
r := rand.New(rand.NewSource(time.Now().Unix()))
for len(slice) > 0 {
n := len(slice)
randIndex := r.Intn(n)
slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1]
slice = slice[:n-1]
}
}
//随机打乱
Shuffle(addArgs)
//添加
ret, err := redisdb.ZAddNX("sortset_test", addArgs...).Result()
log.Println(ret, err)
//获取指定成员score
score, err := redisdb.ZScore("sortset_test", "a_10").Result()
log.Println(score, err)
//获取制定成员的索引
index, err := redisdb.ZRank("sortset_test", "a_50").Result()
log.Println(index, err)
count, err := redisdb.SCard("sortset_test").Result()
log.Println(count, err)
//返回有序集合指定区间内的成员
rets, err := redisdb.ZRange("sortset_test", 10, 20).Result()
log.Println(rets, err)
//返回有序集合指定区间内的成员分数从高到低
rets, err = redisdb.ZRevRange("sortset_test", 10, 20).Result()
log.Println(rets, err)
//指定分数区间的成员列表
rets, err = redisdb.ZRangeByScore("sortset_test", redis.ZRangeBy{Min: "(30", Max: "(50", Offset: 1, Count: 10}).Result()
log.Println(rets, err)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# zset 使用2
func redisExample2() {
zsetKey := "language_rank"
languages := []*redis.Z{
&redis.Z{Score: 90.0, Member: "Golang"},
&redis.Z{Score: 98.0, Member: "Java"},
&redis.Z{Score: 95.0, Member: "Python"},
&redis.Z{Score: 97.0, Member: "JavaScript"},
&redis.Z{Score: 99.0, Member: "C/C++"},
}
// ZADD
num, err := redisdb.ZAdd(zsetKey, languages...).Result()
if err != nil {
fmt.Printf("zadd failed, err:%v\n", err)
return
}
fmt.Printf("zadd %d succ.\n", num)
// 把Golang的分数加10
newScore, err := redisdb.ZIncrBy(zsetKey, 10.0, "Golang").Result()
if err != nil {
fmt.Printf("zincrby failed, err:%v\n", err)
return
}
fmt.Printf("Golang's score is %f now.\n", newScore)
// 取分数最高的3个
ret, err := redisdb.ZRevRangeWithScores(zsetKey, 0, 2).Result()
if err != nil {
fmt.Printf("zrevrange failed, err:%v\n", err)
return
}
for _, z := range ret {
fmt.Println(z.Member, z.Score)
}
// 取95~100分的
op := &redis.ZRangeBy{
Min: "95",
Max: "100",
}
ret, err = redisdb.ZRangeByScoreWithScores(zsetKey, op).Result()
if err != nil {
fmt.Printf("zrangebyscore failed, err:%v\n", err)
return
}
for _, z := range ret {
fmt.Println(z.Member, z.Score)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 其他操作
//用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
//每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数
func ExampleClient_HyperLogLog() {
log.Println("ExampleClient_HyperLogLog")
defer log.Println("ExampleClient_HyperLogLog")
for i := 0; i < 10000; i++ {
redisdb.PFAdd("pf_test_1", fmt.Sprintf("pfkey%d", i))
}
ret, err := redisdb.PFCount("pf_test_1").Result()
log.Println(ret, err)
for i := 0; i < 10000; i++ {
redisdb.PFAdd("pf_test_2", fmt.Sprintf("pfkey%d", i))
}
ret, err = redisdb.PFCount("pf_test_2").Result()
log.Println(ret, err)
redisdb.PFMerge("pf_test", "pf_test_2", "pf_test_1")
ret, err = redisdb.PFCount("pf_test").Result()
log.Println(ret, err)
}
func ExampleClient_PubSub() {
log.Println("ExampleClient_PubSub")
defer log.Println("ExampleClient_PubSub")
//发布订阅
pubsub := redisdb.Subscribe("subkey")
_, err := pubsub.Receive()
if err != nil {
log.Fatal("pubsub.Receive")
}
ch := pubsub.Channel()
time.AfterFunc(1*time.Second, func() {
log.Println("Publish")
err = redisdb.Publish("subkey", "test publish 1").Err()
if err != nil {
log.Fatal("redisdb.Publish", err)
}
redisdb.Publish("subkey", "test publish 2")
})
for msg := range ch {
log.Println("recv channel:", msg.Channel, msg.Pattern, msg.Payload)
}
}
func ExampleClient_CMD() {
log.Println("ExampleClient_CMD")
defer log.Println("ExampleClient_CMD")
//执行自定义redis命令
Get := func(rdb *redis.Client, key string) *redis.StringCmd {
cmd := redis.NewStringCmd("get", key)
redisdb.Process(cmd)
return cmd
}
v, err := Get(redisdb, "NewStringCmd").Result()
log.Println("NewStringCmd", v, err)
v, err = redisdb.Do("get", "redisdb.do").String()
log.Println("redisdb.Do", v, err)
}
func ExampleClient_Scan() {
log.Println("ExampleClient_Scan")
defer log.Println("ExampleClient_Scan")
//scan
for i := 1; i < 1000; i++ {
redisdb.Set(fmt.Sprintf("skey_%d", i), i, 0)
}
cusor := uint64(0)
for {
keys, retCusor, err := redisdb.Scan(cusor, "skey_*", int64(100)).Result()
log.Println(keys, cusor, err)
cusor = retCusor
if cusor == 0 {
break
}
}
}
func ExampleClient_Tx() {
pipe := redisdb.TxPipeline()
incr := pipe.Incr("tx_pipeline_counter")
pipe.Expire("tx_pipeline_counter", time.Hour)
// Execute
//
// MULTI
// INCR pipeline_counter
// EXPIRE pipeline_counts 3600
// EXEC
//
// using one rdb-server roundtrip.
_, err := pipe.Exec()
fmt.Println(incr.Val(), err)
}
func ExampleClient_Script() {
IncrByXX := redis.NewScript(`
if redis.call("GET", KEYS[1]) ~= false then
return redis.call("INCRBY", KEYS[1], ARGV[1])
end
return false
`)
n, err := IncrByXX.Run(redisdb, []string{"xx_counter"}, 2).Result()
fmt.Println(n, err)
err = redisdb.Set("xx_counter", "40", 0).Err()
if err != nil {
panic(err)
}
n, err = IncrByXX.Run(redisdb, []string{"xx_counter"}, 2).Result()
fmt.Println(n, err)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
上次更新: 2023/04/16, 18:35:33