I'm trying to HSet() structs with pointers.
Example:
cl := redis.NewClient(&redis.Options{
Addr: "localhost:6386",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 100,
})
type pointer struct {
PtrInt *int `redis:"ptrInt"`
PtrStr *string `redis:"ptrStr"`
}
i := 1
s := "s"
p := pointer{&i, &s}
err := cl.HSet(context.Background(), "key", p).Err()
fmt.Println(err)
// redis: can't marshal *int (implement encoding.BinaryMarshaler)
How would you solve this? For some reason, the pointers are not dereferenced, thus I have to save like 30 different structs.
Thank you!
Edit: As pointed out in the comments, it seems like I have to implement the encoding.BinaryMarshaler interface for pointers to simple data types like *int and *string. How would you do that?
So far, my solution is:
func main() {
cl := redis.NewClient(&redis.Options{
Addr: "localhost:6386",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 100,
})
type pointer struct {
PtrInt *int `redis:"ptrInt"`
I int `redis:"int"`
PtrStr *string `redis:"ptrStr"`
}
i := 1
s := "s"
p := pointer{&i, 1, &s}
typ := reflect.TypeOf(p)
val := reflect.ValueOf(p)
for i := 0; i < typ.NumField(); i++ {
// set only, if it's not a pointer
if val.Field(i).Kind() != reflect.Ptr {
err := cl.HSet(context.Background(), "test:1", typ.Field(i).Name, val.Field(i).Interface()).Err()
if err != nil {
t.Errorf("%s", err.Error())
}
}
}
}
go-redis is not handling struct fields so good and somewhere in it's tutorial it said:
You can try and implement the
encoding.BinaryMarshalerfor your typepointerand other types, but it is also time-consuming if you have so many structs with pinter fields.My recommendation is to forget about
structfeature of theredisClient.Hset()and try to usemap[string]interface{}, so you have to convert your structs intomap[string]interface{}. Hopefully this is implemented in many encoding libraries, likejsonormapstructure. For your case, something like this works: