Skip to content

Go Redis

在 Go 中使用 Redis 通常通过第三方库来完成,最常用的 Redis Go 客户端是 github.com/go-redis/redis/v8。它是 Go 语言中功能强大的 Redis 客户端,支持 Redis 的常见操作以及高级功能(如事务、管道、发布/订阅等)。

1. 安装 go-redis 客户端

首先需要安装 go-redis 库:

bash
go get github.com/go-redis/redis/v8

2. 使用 go-redis 连接 Redis

基本的连接和操作 Redis 的步骤如下:

2.1 导入 Redis 包

go
package main

import (
    "fmt"
    "log"
    "github.com/go-redis/redis/v8"
    "context"
)

2.2 创建 Redis 客户端

使用 redis.NewClient 创建一个 Redis 客户端,并配置连接的参数:

go
func main() {
    // 创建一个 context(context 是 Go 中用于取消或超时操作的机制)
    ctx := context.Background()

    // 创建 Redis 客户端
    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", // Redis 服务的地址和端口
        Password: "",               // Redis 密码,如果没有设置可以为空
        DB:       0,                // 使用的数据库索引(默认是 0)
    })

    // 检查 Redis 服务是否可用
    _, err := client.Ping(ctx).Result()
    if err != nil {
        log.Fatalf("Failed to connect to Redis: %v", err)
    }
    fmt.Println("Connected to Redis!")
}

2.3 常见的 Redis 操作

一旦连接成功,就可以进行各种 Redis 操作了。以下是一些常见的操作示例。

设置键值对
go
func main() {
    ctx := context.Background()

    // 创建 Redis 客户端
    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", 
        Password: "",
        DB:       0,
    })

    // 检查连接
    _, err := client.Ping(ctx).Result()
    if err != nil {
        log.Fatalf("Failed to connect to Redis: %v", err)
    }
    fmt.Println("Connected to Redis!")

    // 设置键值对
    err = client.Set(ctx, "name", "John Doe", 0).Err() // 设置 key "name" 为 "John Doe"
    if err != nil {
        log.Fatalf("Could not set key: %v", err)
    }

    fmt.Println("Key set successfully")
}
获取键值对
go
func main() {
    ctx := context.Background()

    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", 
        Password: "",
        DB:       0,
    })

    // 获取键值对
    val, err := client.Get(ctx, "name").Result()
    if err == redis.Nil {
        fmt.Println("Key does not exist")
    } else if err != nil {
        fmt.Println("Error getting key:", err)
    } else {
        fmt.Println("Value:", val) // 输出 "John Doe"
    }
}
删除键
go
func main() {
    ctx := context.Background()

    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", 
        Password: "",
        DB:       0,
    })

    // 删除键
    err := client.Del(ctx, "name").Err()
    if err != nil {
        fmt.Println("Error deleting key:", err)
    } else {
        fmt.Println("Key deleted successfully")
    }
}
增加整数值

Redis 提供了原子操作来增加、减少数字值。例如,可以使用 INCR 命令来增加一个整数值:

go
func main() {
    ctx := context.Background()

    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", 
        Password: "",
        DB:       0,
    })

    // 增加一个键的值
    newValue, err := client.Incr(ctx, "counter").Result()
    if err != nil {
        fmt.Println("Error incrementing counter:", err)
    } else {
        fmt.Println("New counter value:", newValue)
    }
}
使用 Hashes 类型

Redis 支持多种数据结构,Hash 是其中之一,允许将多个键值对存储在一个 Hash 结构中。

go
func main() {
    ctx := context.Background()

    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", 
        Password: "",
        DB:       0,
    })

    // 设置哈希字段
    err := client.HSet(ctx, "user:1000", "name", "John Doe", "age", 30).Err()
    if err != nil {
        fmt.Println("Error setting hash:", err)
    }

    // 获取哈希字段
    name, err := client.HGet(ctx, "user:1000", "name").Result()
    if err != nil {
        fmt.Println("Error getting hash field:", err)
    } else {
        fmt.Println("User name:", name)
    }
}
列表操作

Redis 还提供了列表数据结构,允许你在列表的两端推入或弹出元素。

go
func main() {
    ctx := context.Background()

    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", 
        Password: "",
        DB:       0,
    })

    // 向列表添加元素
    err := client.LPush(ctx, "mylist", "item1", "item2", "item3").Err()
    if err != nil {
        fmt.Println("Error pushing to list:", err)
    }

    // 从列表弹出元素
    item, err := client.LPop(ctx, "mylist").Result()
    if err != nil {
        fmt.Println("Error popping from list:", err)
    } else {
        fmt.Println("Popped item:", item)
    }
}

2.4 使用 defer 关闭 Redis 客户端

虽然 Redis 客户端在程序退出时会自动关闭,但你也可以显式地关闭客户端连接,尤其是在程序中不再使用 Redis 时。可以通过 defer 来保证程序退出时自动关闭连接。

go
func main() {
    ctx := context.Background()

    // 创建 Redis 客户端
    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", 
        Password: "",
        DB:       0,
    })
    defer client.Close()  // 使用 defer 确保退出时关闭连接

    // 执行 Redis 操作
    err := client.Set(ctx, "key", "value", 0).Err()
    if err != nil {
        fmt.Println("Error setting key:", err)
    }
    fmt.Println("Key set successfully")
}

3. 连接池

go-redis 客户端通过连接池来管理 Redis 连接,确保在并发请求时可以高效地重用连接,而不是每次都新建连接。连接池的大小可以在客户端配置中进行调整。

go
client := redis.NewClient(&redis.Options{
    Addr:         "localhost:6379",
    Password:     "",
    DB:           0,
    PoolSize:     10, // 设置连接池大小
    MinIdleConns: 3,  // 设置最低空闲连接数
})

4. Redis Pub/Sub

go-redis 还支持 Redis 的发布/订阅(Pub/Sub)功能,允许客户端接收实时消息。以下是一个简单的例子,展示如何订阅 Redis 频道并接收消息。

go
func main() {
    ctx := context.Background()

    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", 
        Password: "",
        DB:       0,
    })

    // 创建一个 Pub/Sub 客户端
    pubsub := client.Subscribe(ctx, "mychannel")

    // 在另一个 goroutine 中发送消息
    go func() {
        client.Publish(ctx, "mychannel", "Hello, Redis!")
    }()

    // 获取消息
    msg, err := pubsub.ReceiveMessage(ctx)
    if err != nil {
        fmt.Println("Error receiving message:", err)
        return
    }

    fmt.Println("Received message:", msg.Payload)
}

总结

在 Go 中使用 Redis,go-redis 是最常见和最强大的 Redis 客户端库,它支持连接池、事务、管道、发布/订阅等多种功能。通过该库,你可以轻松与 Redis 进行交互,执行各种 Redis 操作,如设置/获取键值、列表、哈希、事务等。