How to separate register of pointer and values?

205 Views Asked by At

I am new to gob and am having confusion on gob register. In my code, I have something like

var foo1 somestruct
var foo2 &somestruct
var foo3 anotherstruct

func call(a interface, b interface) {
    var buf bytes.Buffer
    argsEncoder := gob.NewEncoder(&buf)
    gob.register(a)
    gob.register(b)
    err := argsEncoder.EncodeValue(reflect.ValueOf(&a))
}

And then I have two call of the method: call(foo1,foo3) and call(foo2, foo3). I found that if they run separately, the function works fine. However, if you run them consecutively, it gives gob: registering duplicate names. Is there a way to bypass this problem?

I also found that if I register only once for somestruct, the next call call(foo2, foo3) will also go on well. But when I check with reflect.TypeOf(a), they both gives me the type that was registered (somestruct, not somestruct and *somestruct).

1

There are 1 best solutions below

0
On

encoding/gob maintains a single, global type registry, not a per-encoder one. You can't (shouldn't) register types in your call() function. You should do it once, e.g. in your main() function.

Like this:

func main() {
    gob.Register(somestruct{})
    gob.Register(anotherstruct{})

    // ...
}

Also note that encoding/gob does not transmit pointer values. Quoting from the package doc:

Pointers are not transmitted, but the things they point to are transmitted; that is, the values are flattened. Nil pointers are not permitted, as they have no value.

So you don't have to register pointer and non-pointer types. The decoder will properly decode registered types, and generate pointers to them if the value they are decoded into are pointers to the known types.

Also you should not use pointers to interfaces, ever. The very rare cases when they needed, you'll know when you get there.

That said, &a is a pointer to interface because type of a is interface{}. This isn't needed, because interface values may wrap pointers.

You also shouldn't encode reflect.Value values. Encode a itself.