因为 Go
标准库中是没提供 redis
的库,所以我们选择用 go-redis
这个第三方库。源码地址为 https://github.com/go-redis/redis
在命令行中使用 go get
来安装
go get github.com/go-redis/redis
在进行代码之前,需要先安装 redis,安装指导请参考:https://blog.csdn.net/wohu1104/article/details/86755570
通过 redis.NewClient
函数创建一个 Redis
客户端,并通过 redis.Options
配置 Redis
相关的属性,例如 Redis
服务器地址、数据库名、数据库密码等。
package main
import (
"fmt"
"github.com/go-redis/redis"
)
var client *redis.Client
func initClient() error {
// 创建 redis 客户端
client = redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 10, // 连接池的大小为 10
})
//defer client.Close()
// 通过 cient.Ping() 来检查是否成功连接到了 redis 服务器
pong, err := client.Ping().Result()
fmt.Println("Redis Client: " + pong)
return err
}
func main() {
initClient()
}
在 Redis
中 string
比较常用的类型,所有键值均是字符串对象。
func operateString() {
// 第三个参数是过期时间, 如果是0, 则表示没有过期时间.
err := client.Set("name", "wohu", 0).Err()
if err != nil {
fmt.Printf("set name error: %v\n", err)
return
}
err = client.Set("age", 20, 0).Err()
if err != nil {
fmt.Printf("set age error: %v\n", err)
return
}
// 获取某值
userName, err := client.Get("name").Result()
if err != nil {
fmt.Printf("get user_name error: %v\n", err)
return
}
fmt.Println("get name", userName)
userAge, err := client.Get("age").Result()
if err != nil {
fmt.Printf("get age error: %v\n", err)
return
}
fmt.Println("get age", userAge)
}
查看 redis 并获取值,与代码执行一致。
ubuntu@wohu:/$ redis-cli
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> get name
"wohu"
127.0.0.1:6379> get age
"20"
127.0.0.1:6379>
func operateList() {
// 从列表的尾部进行添加
err := client.RPush("message", "01").Err()
if err != nil {
fmt.Printf("rpush message error: %v\n", err)
return
}
// 从列表的头部进行添加
err = client.LPush("message", "02").Err()
if err != nil {
fmt.Printf("lpush message error: %v\n", err)
return
}
// 从列表尾部弹出元素
message, err := client.RPop("message").Result()
if err != nil {
fmt.Printf("rpop message error: %v\n", err)
return
}
fmt.Println("rpop message: ", message)
// 获取长度
length, err := client.LLen("message").Result()
if err != nil {
fmt.Printf("llen message error: %v\n", err)
return
}
fmt.Println("message length: ", length)
}
redis 查询结果:
127.0.0.1:6379> lrange message 0 -1
1) "02"
127.0.0.1:6379>
这是一个没有无序数组且不能有重复,其叫无序集合:
func operateSet() {
// 向 set_test 中添加元素
client.SAdd("set_test", "name")
client.SAdd("set_test", "age")
client.SAdd("set_test", "gender")
// 判断 name 是否在集合中
isMember, err := client.SIsMember("set_test", "name").Result()
if err != nil {
fmt.Printf("sismember set_test error: %v\n", err)
return
}
fmt.Println("sismember set_test:", isMember)
// 获取集合 set_test 中所有的元素
all, err := client.SMembers("set_test").Result()
if err != nil {
fmt.Printf("smembers set_test error: %v\n", err)
return
}
fmt.Println("smembers set_test: ", all)
}
127.0.0.1:6379> smembers set_test
1) "name"
2) "age"
3) "gender"
127.0.0.1:6379>
func operateHash() {
// 向 hash 类型添加元素
client.HSet("student", "name", "jack")
client.HSet("student", "age", 18)
// 批量地向名称为 student 的 hash 中添加元素
client.HMSet("user", map[string]interface{}{"id": 1, "time": "2020-03-31"})
// 批量获取名为 student 的 hash 中的指定字段的值.
fields, err := client.HMGet("student", "name", "age").Result()
if err != nil {
fmt.Printf("hmget user error: %v\n", err)
return
}
fmt.Println("hmget user: ", fields)
// 获取名为 student 的 hash 中的字段个数
length, err := client.HLen("student").Result()
if err != nil {
fmt.Printf("hlen student error: %v\n", err)
return
}
fmt.Println("hlen user: ", length)
}
参考:
https://github.com/go-redis/redis
https://gitbook.cn/books/5e7637996ba17a6d2c9a3352/index.html
https://github.com/fwhezfwhez/gitchat/tree/master/chat1-web%E5%90%8E%E7%AB%AF%E5%AE%9E%E6%88%98
https://github.com/go-redis/redis
https://redis.uptrace.dev/guide/#installation
安装
go get github.com/go-redis/redis/v8
注意:v8 在导入路径中
代码实现
package main
import (
"context"
"fmt"
"time"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
func main() {
rdb := redis.NewClient(
&redis.Options{
Network: "tcp",
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
DialTimeout: 3 * time.Second, // no time unit = seconds
ReadTimeout: 6 * time.Second,
MaxRetries: 2,
})
err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
}
// 当服务器返回 nil 时, go-redis 返回 redis.Nil
// BLPOP and ZSCORE 也都会返回 redis.Nil
val, err := rdb.Get(ctx, "b").Result()
switch {
case err == redis.Nil:
fmt.Println("key does not exist")
case err != nil:
fmt.Println("Get failed", err)
case val == "":
fmt.Println("value is empty")
}
fmt.Println("===", val)
// or 可以保存该命令,以后再分别访问该值和错误
ret := rdb.Get(ctx, "b")
fmt.Println(ret.Val(), ret.Err())
// 执行任意或者自定义命令
v, err := rdb.Do(ctx, "get", "key").Result()
if err != nil {
if err == redis.Nil {
fmt.Println("key does not exists")
return
}
panic(err)
}
fmt.Println(v.(string))
// Do 返回一个 Cmd 结构,该结构有很多方法来处理 interface{} 值
// Text is a shortcut for get.Val().(string) with proper error handling.
val, err = rdb.Do(ctx, "get", "key").Text()
fmt.Println(val, err)
/*
s, err := cmd.Text()
flag, err := cmd.Bool()
num, err := cmd.Int()
num, err := cmd.Int64()
num, err := cmd.Uint64()
num, err := cmd.Float32()
num, err := cmd.Float64()
ss, err := cmd.StringSlice()
ns, err := cmd.Int64Slice()
ns, err := cmd.Uint64Slice()
fs, err := cmd.Float32Slice()
fs, err := cmd.Float64Slice()
bs, err := cmd.BoolSlice()
*/
// 发布订阅模式
// go-redis允许发布消息和订阅频道。它还能自动处理重新连接的问题。
err = rdb.Publish(ctx, "mychannel1", "payload").Err()
if err != nil {
panic(err)
}
// There is no error because go-redis automatically reconnects on error.
pubsub := rdb.Subscribe(ctx, "mychannel1")
// Close the subscription when we are done.
defer pubsub.Close()
// To receive a message:
for {
msg, err := pubsub.ReceiveMessage(ctx)
if err != nil {
panic(err)
}
fmt.Println(msg.Channel, msg.Payload)
}
// But the simplest way is using a Go channel which is closed together with subscription:
ch := pubsub.Channel()
for msg := range ch {
fmt.Println(msg.Channel, msg.Payload)
}
// SET key value EX 10 NX
set, err := rdb.SetNX(ctx, "key", "value", 10*time.Second).Result()
// SET key value keepttl NX
set, err := rdb.SetNX(ctx, "key", "value", redis.KeepTTL).Result()
// SORT list LIMIT 0 2 ASC
vals, err := rdb.Sort(ctx, "list", &redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result()
// ZRANGEBYSCORE zset -inf +inf WITHSCORES LIMIT 0 2
vals, err := rdb.ZRangeByScoreWithScores(ctx, "zset", &redis.ZRangeBy{
Min: "-inf",
Max: "+inf",
Offset: 0,
Count: 2,
}).Result()
// ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM
vals, err := rdb.ZInterStore(ctx, "out", &redis.ZStore{
Keys: []string{"zset1", "zset2"},
Weights: []int64{2, 3},
}).Result()
// EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello"
vals, err := rdb.Eval(ctx, "return {KEYS[1],ARGV[1]}", []string{"key"}, "hello").Result()
// custom command
res, err := rdb.Do(ctx, "set", "key", "value").Result()
}