Go 客户端基础
本章介绍 go-redis 客户端的基本使用,包括连接、配置和常用操作。
安装
bash
go get github.com/redis/go-redis/v9连接客户端
基本连接
go
package main
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
ctx := context.Background()
// 测试连接
pong, err := rdb.Ping(ctx).Result()
if err != nil {
panic(err)
}
fmt.Println(pong) // PONG
}完整配置
go
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
PoolSize: 10,
MinIdleConns: 5,
MaxRetries: 3,
DialTimeout: 5 * time.Second,
ReadTimeout: 3 * time.Second,
WriteTimeout: 3 * time.Second,
})集群连接
go
rdb := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{
"node1:6379",
"node2:6379",
"node3:6379",
},
Password: "",
})基本操作
String 操作
go
ctx := context.Background()
// Set
err := rdb.Set(ctx, "key", "value", 0).Err()
// Set with TTL
rdb.Set(ctx, "key", "value", 10*time.Minute)
// Get
val, err := rdb.Get(ctx, "key").Result()
if err == redis.Nil {
fmt.Println("key does not exist")
}
// SetNX
ok, _ := rdb.SetNX(ctx, "lock", "owner", 10*time.Second).Result()
// MSet/MGet
rdb.MSet(ctx, "key1", "value1", "key2", "value2")
vals, _ := rdb.MGet(ctx, "key1", "key2").Result()
// Incr/Decr
rdb.Incr(ctx, "counter")
rdb.IncrBy(ctx, "counter", 10)
rdb.Decr(ctx, "counter")Hash 操作
go
// HSet
rdb.HSet(ctx, "user:1001", "name", "Alice")
rdb.HSet(ctx, "user:1001", map[string]interface{}{
"age": 25,
"email": "alice@example.com",
})
// HGet
name, _ := rdb.HGet(ctx, "user:1001", "name").Result()
// HGetAll
fields, _ := rdb.HGetAll(ctx, "user:1001").Result()
// HDel
rdb.HDel(ctx, "user:1001", "age")
// HIncrBy
rdb.HIncrBy(ctx, "user:1001", "age", 1)List 操作
go
// LPush/RPush
rdb.LPush(ctx, "mylist", "value1")
rdb.RPush(ctx, "mylist", "value2")
// LRange
vals, _ := rdb.LRange(ctx, "mylist", 0, -1).Result()
// LPop/RPop
val, _ := rdb.LPop(ctx, "mylist").Result()
// LLen
len, _ := rdb.LLen(ctx, "mylist").Result()
// BRPop (阻塞)
result, _ := rdb.BRPop(ctx, 0, "mylist").Result()Set 操作
go
// SAdd
rdb.SAdd(ctx, "myset", "member1", "member2")
// SMembers
members, _ := rdb.SMembers(ctx, "myset").Result()
// SIsMember
isMember, _ := rdb.SIsMember(ctx, "myset", "member1").Result()
// SRem
rdb.SRem(ctx, "myset", "member1")
// SInter
intersection, _ := rdb.SInter(ctx, "set1", "set2").Result()ZSet 操作
go
// ZAdd
rdb.ZAdd(ctx, "leaderboard", redis.Z{Score: 100, Member: "user1"})
// ZRange
members, _ := rdb.ZRange(ctx, "leaderboard", 0, -1).Result()
// ZRangeWithScores
membersWithScores, _ := rdb.ZRevRangeWithScores(ctx, "leaderboard", 0, 9).Result()
// ZScore
score, _ := rdb.ZScore(ctx, "leaderboard", "user1").Result()
// ZRank
rank, _ := rdb.ZRevRank(ctx, "leaderboard", "user1").Result()高级特性
Pipeline
批量执行命令,减少网络往返。
go
pipe := rdb.Pipeline()
cmd1 := pipe.Get(ctx, "key1")
cmd2 := pipe.Get(ctx, "key2")
cmd3 := pipe.Get(ctx, "key3")
_, err := pipe.Exec(ctx)
if err != nil {
panic(err)
}
fmt.Println(cmd1.Val(), cmd2.Val(), cmd3.Val())事务
go
err := rdb.Watch(ctx, func(tx *redis.Tx) error {
n, err := tx.Get(ctx, "key").Int64()
if err != nil && err != redis.Nil {
return err
}
_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
pipe.Set(ctx, "key", n+1, 0)
return nil
})
return err
}, "key")Pub/Sub
go
// 订阅
pubsub := rdb.Subscribe(ctx, "channel1", "channel2")
// 接收消息
for msg := range pubsub.Channel() {
fmt.Println(msg.Channel, msg.Payload)
}
// 发布
rdb.Publish(ctx, "channel1", "message")Scan
遍历键。
go
var cursor uint64
for {
var keys []string
var err error
keys, cursor, err = rdb.Scan(ctx, cursor, "user:*", 10).Result()
if err != nil {
panic(err)
}
for _, key := range keys {
fmt.Println(key)
}
if cursor == 0 {
break
}
}错误处理
go
import "github.com/redis/go-redis/v9"
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
if err == redis.Nil {
fmt.Println("key does not exist")
} else {
fmt.Println("error:", err)
}
return
}最佳实践
- 使用连接池:PoolSize 和 MinIdleConns
- 设置超时:DialTimeout、ReadTimeout、WriteTimeout
- 使用 Pipeline:批量操作减少网络往返
- 合理设置 TTL:避免内存泄漏
- 错误处理:区分键不存在和其他错误
在下一章中,我们将学习 Redis 的持久化机制。