I'm using redigo to store and retrieve data in redigo.
I have a struct that contains a type definition following time. I want to store the struct Data using HSET in Redis. I have a type definition to be able to use ScanStruct by adding a function RedisScan to my Timestamp type.
The problem is that Redis stores the Timestamp as ext, wall, loc following the time fields. You can't create a new Time object from these fields so that's fairly useless. What is the proper way to serialize a struct for 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)
}
The
redis.ScanStructfunction and theArgs.AddFlatmethod 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:
Adjust the code as needed to match the Redis hash field definitions. Here's the code for time in RFC 3339 format:
The
Readexamples 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 thefieldsvariable andScanStructnonsense with a call toredis.Int64(conn.Do("HGET", key, "timestamp")orredis.String(conn.Do("HGET", key, "timestamp")