msgpack icon indicating copy to clipboard operation
msgpack copied to clipboard

Types with pointer receivers that are not pointers cause do not encode

Open element-of-surprise opened this issue 9 months ago • 0 comments

If you try to encode a type with pointer receivers on the type, but is not a pointer, you get an error:

msgpack: Encode(non-addressable main.Operation)

So, for example:

type Operation uint16

func (o *Operation) MarshalMsgpack() ([]byte, error) {
	return msgpack.Marshal(o)
}

func (o *Operation) UnmarshalMsgpack(b []byte) error {
	return msgpack.Unmarshal(b, o)
}

You cannot use mgspack.Marshal(Operation(1)).

Now, if you change MarshalMsgpack() to have a value receiver instead, this works:

func (o Operation) MarshalMsgpack() ([]byte, error) {
	return msgpack.Marshal(o)
}

Without the pointer, this will encode fine. This is in version v4 and v5. I'm currently using v4 due to the other issues I have reported in the previous weeks.

Here are some playgrounds:

https://go.dev/play/p/fVySSbkpz93 -- does not work https://go.dev/play/p/0zeobarO3fD -- works because I made it a value receiver

Expected Behavior

Should encode with no error.

Current Behavior

msgpack: Encode(non-addressable main.Operation)

Possible Solution

This is some type of tricky reflection problem. My guess is that you have to do something like:

reflect.ValueOf(v).Addr()

Then you can probably work on it.

The most definitive work around reflection decoding that would mirror what you are doing: https://github.com/go-json-experiment/json

Steps to Reproduce

https://go.dev/play/p/fVySSbkpz93 -- does not work https://go.dev/play/p/0zeobarO3fD -- works because I made it a value receiver

Context (Environment)

It makes it so that you have a type that can't fit into interfaces with all methods. For me, this affected some testing stuff, but I found clever (aka confusing for maintainers) way around the problem.

element-of-surprise avatar May 06 '24 16:05 element-of-surprise