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)
}
2
Answers
The
redis.ScanStruct
function and theArgs.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:
Adjust the code as needed to match the Redis hash field definitions. Here’s the code for time in RFC 3339 format:
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 thefields
variable andScanStruct
nonsense with a call toredis.Int64(conn.Do("HGET", key, "timestamp")
orredis.String(conn.Do("HGET", key, "timestamp")
If you are going to add something into Hash Set of Redis you need to have these three values at least.
Best way of coding this is to add a wrapper on the redigo library to abstract the implementation and inject the dependency into your code.