1

I am trying to read a gob-encoded Go object into a variable of interface type. When I let gob to the encoding itself, my code works (see below). In contrast, when I try to encode/decode the object manually, using MarshalBinary and UnmarshalBinary, my program crashes with the following message:

panic: interface conversion: interface is nil, not encoding.BinaryUnmarshaler [recovered]
    panic: interface conversion: interface is nil, not encoding.BinaryUnmarshaler

What am I doing wrong?

Details. The interface I am using is given by

type Duck interface {
    encoding.BinaryMarshaler
    encoding.BinaryUnmarshaler
    Quack()
}

The actual object I am encoding and trying to decode is

type A struct {
    x byte
}

func (a *A) MarshalBinary() ([]byte, error) {
    return []byte{a.x}, nil
}

func (a *A) UnmarshalBinary(data []byte) error {
    a.x = data[0]
    return nil
}

func (a *A) Quack() {
    fmt.Println(a.x)
}

I have registered the type with gob using

gob.Register(&A{})

and encoding objects of type &A seems to work fine. I try to gob-decode the object into an interface variable using the commands

dec := gob.NewDecoder(buf)
var duck2 Duck
dec.Decode(&duck2)

The last of these commands results in the panic shown above.

Full code is on play.golang.org.

Updated. Without the custom en-/decoder, the code works (after renaming a.x to a.X, to make the field globally visible): https://play.golang.org/p/y8nWNhObUwb

jochen
  • 3,728
  • 2
  • 39
  • 49
  • 1
    You don't want to marshal or unmarshal the interface, you want to marshal and unmarshal the struct. https://play.golang.org/p/_QdYcjV9GTo – sberry Aug 13 '19 at 21:58
  • @sberry I want to read the result into an interface variable, without having to know in advance which concrete type I'm receiving (the actual interface has several possible implementations, and gob data comes in over a network connection). So, while your code avoids the panic, it does not solve my problem. – jochen Aug 13 '19 at 22:05
  • Does it work without your customer marshaling / unmarshaling (will need to export the X field then) – sberry Aug 13 '19 at 22:40
  • @sberry Yes, it does! See https://play.golang.org/p/y8nWNhObUwb . I've added this link to my question, to make it easier to find. – jochen Aug 13 '19 at 22:55
  • https://play.golang.org/p/m6s88GzQDE0 – beiping96 Aug 15 '19 at 08:35
  • @beiping96 yes, I had thought about this. Initialising the interface object makes the "interface is nil" error go away. But for this to work I need to know the concrete type in advance (which I don't). – jochen Aug 15 '19 at 15:54
  • Seems to be caused by the same problem as here: https://stackoverflow.com/questions/43324919/gob-panics-decoding-an-interface The interface's `UnmarshalBinary` implementation takes, unfortunately, precedence over gob's handling of registered interface implementations. So gob doesn't even transfer type information. – sebastian Feb 22 '22 at 18:26

0 Answers0