Can't marshal, (implement encoding.BinaryMarshaler). go-redis Sdd with multiple objects
Asked Answered
S

3

6

I have a following piece of code in which I am trying to add an array to a redis set but it is giving me an error.

package main

import (
    "encoding/json"
    "fmt"

    "github.com/go-redis/redis"
)

type Info struct {
    Name string
    Age  int
}

func (i *Info) MarshalBinary() ([]byte, error) {
    return json.Marshal(i)
}
func main() {
    client := redis.NewClient(&redis.Options{
        Addr:        "localhost:6379",
        Password:    "",
        DB:          0,
        ReadTimeout: -1,
    })

    pong, err := client.Ping().Result()

    fmt.Print(pong, err)

    infos := [2]Info{
        {
            Name: "tom",
            Age:  20,
        },
        {
            Name: "john doe",
            Age:  30,
        },
    }

    pipe := client.Pipeline()
    pipe.Del("testing_set")
    // also tried this
    // pipe.SAdd("testing_set", []interface{}{infos[0], infos[1]})
    pipe.SAdd("testing_set", infos)
    _, err = pipe.Exec()
    fmt.Println(err)
}


I get the error can't marshal [2]main.Info (implement encoding.BinaryMarshaler)

I have also tried to convert each info to []byte and pass in the [][]byte... to SAdd but same error. How would I do this idomatically?

Sharlenesharline answered 30/3, 2020 at 6:34 Comment(2)
Ask the author of the github.com/go-redis/redis. The documentation of how redis serializes type is a bit spare.Faceoff
yeah. it workds fine when i pass a single []byte(info). it should work fine with [][]bytes... but it does notSharlenesharline
S
20

MarshalBinary() method should be as below

func (i Info) MarshalBinary() ([]byte, error) {
    return json.Marshal(i)
}

note: Info instead of *Info

Sagacity answered 25/12, 2020 at 13:13 Comment(0)
P
5

Redis is based on key-value pairs, and key-values are all strings and other string-based data structures. Therefore, if you want to put some data into redis, you should make these data strings.

I think you should implement this interface like code below to make go-redis able to stringify your type:

func (i Info) MarshalBinary() (data []byte, err error) {
    bytes, err := json.Marshal(i) \\edited - changed to i
    return bytes, err
}

In this way, you implement this method and go-redis will call this method to stringify(or marshal) your data.

Piggin answered 1/6, 2021 at 4:24 Comment(0)
P
0

Answer to the original question, here you need to implement MarshalBinary() method for [2]Info I know it's kind of strange but that's how we need to do it

Solution

type Infos [2]Info

func (i Infos) MarshalBinary() ([]byte, error) {
    return json.Marshal(i)
}

refer : https://github.com/redis/go-redis/issues/1554

Portly answered 12/10, 2023 at 10:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.