在Go项目开发中,经常需要将业务相关的结构体数组持久化到Redis中,后续再从Redis读取恢复数据,Redigo作为成熟的Redis客户端库可以很好地完成这个需求,核心是需要对结构体数组进行序列化处理后再存储,读取时再反序列化。

环境准备与依赖安装
首先需要安装Redigo库,执行以下命令完成依赖引入:
go get github.com/gomodule/redigo/redis
定义结构体与初始化Redis连接
首先定义需要存储的结构体,这里以用户结构体为例,同时创建Redis连接池,避免频繁创建连接带来的性能损耗。
package main
import (
"encoding/json"
"fmt"
"github.com/gomodule/redigo/redis"
)
// 定义用户结构体
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
}
// 创建Redis连接池
func newRedisPool() *redis.Pool {
return &redis.Pool{
MaxIdle: 5,
MaxActive: 10,
IdleTimeout: 300,
Dial: func() (redis.Conn, error) {
conn, err := redis.Dial("tcp", "127.0.0.1:6379")
if err != nil {
return nil, err
}
return conn, nil
},
}
}
将结构体数组存入Redis
结构体数组无法直接存入Redis,需要先序列化为JSON字符串,再使用Redigo的SET命令存储,这里选择JSON作为序列化方式,通用性更强。
func saveUserListToRedis(pool *redis.Pool, key string, users []User) error {
conn := pool.Get()
defer conn.Close()
// 序列化结构体数组为JSON字节
userBytes, err := json.Marshal(users)
if err != nil {
return fmt.Errorf("序列化结构体数组失败: %v", err)
}
// 存入Redis,设置过期时间3600秒
_, err = conn.Do("SET", key, userBytes, "EX", 3600)
if err != nil {
return fmt.Errorf("存入Redis失败: %v", err)
}
return nil
}
从Redis读取结构体数组
读取时先获取Redis中存储的字符串,再反序列化为结构体数组,需要注意处理键不存在的情况。
func getUserListFromRedis(pool *redis.Pool, key string) ([]User, error) {
conn := pool.Get()
defer conn.Close()
// 从Redis获取字符串
reply, err := redis.Bytes(conn.Do("GET", key))
if err != nil {
if err == redis.ErrNil {
return nil, fmt.Errorf("Redis中不存在键为%s的数据", key)
}
return nil, fmt.Errorf("从Redis读取失败: %v", err)
}
// 反序列化JSON为结构体数组
var users []User
err = json.Unmarshal(reply, &users)
if err != nil {
return nil, fmt.Errorf("反序列化失败: %v", err)
}
return users, nil
}
完整调用示例
以下是完整的调用逻辑,包含数据准备、存储、读取和结果打印。
func main() {
// 初始化Redis连接池
pool := newRedisPool()
defer pool.Close()
// 准备结构体数组数据
userList := []User{
{ID: 1, Name: "张三", Age: 20},
{ID: 2, Name: "李四", Age: 22},
{ID: 3, Name: "王五", Age: 25},
}
// 存入Redis
redisKey := "user_list"
err := saveUserListToRedis(pool, redisKey, userList)
if err != nil {
fmt.Printf("存储失败: %vn", err)
return
}
fmt.Println("结构体数组已成功存入Redis")
// 从Redis读取
result, err := getUserListFromRedis(pool, redisKey)
if err != nil {
fmt.Printf("读取失败: %vn", err)
return
}
// 打印读取结果
fmt.Println("从Redis读取的结构体数组:")
for _, u := range result {
fmt.Printf("ID: %d, 姓名: %s, 年龄: %dn", u.ID, u.Name, u.Age)
}
}
注意事项
- 序列化方式可以选择JSON、Gob等,JSON通用性更好,Gob是Go原生序列化方式,性能更优
- 存储时建议设置合理的过期时间,避免Redis内存占用过高
- 读取时需要先判断键是否存在,避免空指针或反序列化错误
- 如果结构体包含不可导出的字段,JSON序列化时会被忽略,需要提前确认字段的可导出性