【问题标题】:How to HSET time in Golang to redigo (Redis)?如何将 Golang 中的 HSET 时间转换为 redigo(Redis)?
【发布时间】:2021-06-29 07:42:15
【问题描述】:

我正在使用 redigo 在 redigo 中存储和检索数据。 我有一个结构,其中包含一个类型定义。我想在 Redis 中使用 HSET 存储结构 Data。我有一个类型定义,可以通过将函数 RedisScan 添加到我的 Timestamp 类型来使用 ScanStruct

问题在于 Redis 将 Timestamp 存储为 ext, wall, loc 之后的时间 fields。您不能从这些字段中创建新的 Time 对象,因此这毫无用处。为 redigo 序列化结构的正确方法是什么?

type Timestamp time.Time

func (t *Timestamp) RedisScan(x interface{}) error {
    ...
}

type Data struct {
    Timestamp  Timestamp `redis:"timestamp"`
}

func (r *RedisRepo) Write(data Data, key String) error {
    conn := r.pool.Get()
    defer conn.Close()
    conn.Send("HSET", redis.Args{key}.AddFlat(data)...)     
}

func (r *RedisRepo) Read(key string) (*Data, error) {
    var data Data
    conn := r.pool.Get()
    defer conn.Close()
    v, err := redis.Values(conn.Do("HGETALL", key))
    return redis.ScanStruct(v, &data)
}

【问题讨论】:

    标签: go redis redigo


    【解决方案1】:

    redis.ScanStruct 函数和 Args.AddFlat 方法缺少使该对可用作通用编组/解组函数的功能。

    解决问题的方法取决于您的目标。​​​ 如果您的目标是加载和保存结构,而不是访问 Redis 哈希,请参阅 Save generic struct to redis

    如果您的目标是使用已定义的名称和值访问 Redis 哈希,则编写在这些定义和 Go 值之间进行转换的代码。下面是一个散列示例,该散列定义为具有字段“timestamp”,其值为十进制编码的 Unix 秒:

    type Data struct {
        Timestamp time.Time
    }
    
    func (r *RedisRepo) Write(data Data, key string) error {
        conn := r.pool.Get()
        defer conn.Close()
        _, err := conn.Do("HSET", key, "timestamp", data.Timestamp.Unix())
        return err
    }
    
    func (r *RedisRepo) Read(key string) (*Data, error) {
        conn := r.pool.Get()
        defer conn.Close()
        v, err := redis.Values(conn.Do("HGETALL", key))
        if err != nil {
            return nil, err
        }
    
        var fields struct {
            Timestamp int64 `redis:"timestamp"`
        }
    
        err = redis.ScanStruct(v, &fields)
        if err != nil {
            return nil, err
        }
        return &Data{Timestamp: time.Unix(fields.Timestamp, 0)}, nil
    }
    

    根据需要调整代码以匹配 Redis 哈希字段定义。这是RFC 3339格式的时间代码:

    type Data struct {
        Timestamp time.Time
    }
    
    func (r *RedisRepo) Write(data Data, key string) error {
        conn := r.pool.Get()
        defer conn.Close()
        _, err := conn.Do("HSET", key, "timestamp", data.Timestamp.Format(time.RFC3339))
        return err
    }
    
    func (r *RedisRepo) Read(key string) (*Data, error) {
        conn := r.pool.Get()
        defer conn.Close()
        v, err := redis.Values(conn.Do("HGETALL", key))
        if err != nil {
            return nil, err
        }
    
        var fields struct {
            Timestamp string `redis:"timestamp"`
        }
    
        err = redis.ScanStruct(v, &fields)
        if err != nil {
            return nil, err
        }
        t, err := time.Parse(time.RFC3339, fields.Timestamp)
        if err != nil {
            return nil, err
        }
        return &Data{Timestamp: t}, nil
    }
    

    上面的Read 示例是这样编写的,以便示例易于扩展到多个字段。如果应用程序只需要访问单个字段,请将fields 变量和ScanStruct 废话替换为对redis.Int64(conn.Do("HGET", key, "timestamp")redis.String(conn.Do("HGET", key, "timestamp") 的调用

    【讨论】:

    • 谢谢。我特别想使用 redis 哈希。我虽然只是从格林威治标准时间存储 unix 秒,这将起作用。最后我希望有一个结构的翻译功能 - > redis哈希(比如redis.Args{key}.AddFlat(data),它可以进行某种序列化。一个结构可能有很多字段。手动设置所有字段很不方便。可能会向redigo提出一些建议. 另一种机制可能是:conn.Do("HSET", redis.Args{key}.AddFlat(data)...) \n conn.Do("HSET", key, "timestamp", data.Timestamp.Format(time.RFC3339))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 2017-10-10
    • 1970-01-01
    相关资源
    最近更新 更多