The redis.ScanStruct
function and the Args.AddFlat
method are missing features that make the pair usable as general purpose marshal/unmarshal functions.
The approach for fixing the problem depends on what your goal is.
See Save generic struct to redis if your goal is to load and save structs, not to access a Redis hash.
If your goal is to access Redis hashes with defined names and values, then write code that translates between those definitions and Go values. Here's an example for a hash that's defined to have field "timestamp" with a value as decimal encoded Unix seconds:
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
}
Adjust the code as needed to match the Redis hash field definitions. Here's the code for time in RFC 3339 format:
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
}
The Read
examples above are written so that the examples are easy to extend to multiple fields. If the application only needs to access a single field, replace the fields
variable and ScanStruct
nonsense with a call to redis.Int64(conn.Do("HGET", key, "timestamp")
or redis.String(conn.Do("HGET", key, "timestamp")