Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

encoding/gob: "wrong type for received field" when decoding slices of pointers #2995

Closed
patrickmn opened this issue Feb 12, 2012 · 5 comments
Milestone

Comments

@patrickmn
Copy link

What steps will reproduce the problem?
1. Try to encode, then decode a []*Object where Object.Children = []*Object


What is the expected output?
No error


What do you see instead? In Decoder.Decode: "gob: wrong type ([]*main.Object) for
received field .Children"
(because Object.Children[0].Children is nil?)


Which compiler are you using (5g, 6g, 8g, gccgo)? 6g


Which operating system are you using? Linux


Which revision are you using? 7e665c5da059 tip


Example:

This only seems to happen when you haven't first set a precedent by encoding a []Object
(regardless if it's a different encoder). Running gob.Register on an []Object does not
have the same effect.

package main

import (
    "bytes"
    "encoding/gob"
    "testing"
)

type Object struct {
    Num      int
    Children []*Object
}

func TestGobPtrSlices(t *testing.T) {
    var err error
    b := &bytes.Buffer{}

    // Works if you uncomment this
    // fos := []Object{
    //  Object{1, nil},
    //  Object{2, nil},
    // }
    // err = gob.NewEncoder(b).Encode(&fos)
    // if err != nil {
    //  t.Fatal("Couldn't encode:", err)
    // }
    // var nfos []Object
    // err = gob.NewDecoder(b).Decode(&nfos)
    // if err != nil {
    //  t.Fatal("Couldn't decode:", err)
    // }

    os := []*Object{
        &Object{1, nil},
        &Object{2, nil},
    }
    err = gob.NewEncoder(b).Encode(&os)
    if err != nil {
        t.Fatal("Couldn't encode:", err)
    }

    var nos []*Object
    err = gob.NewDecoder(b).Decode(&nos)
    if err != nil {
        t.Fatal("Couldn't decode:", err)
    }
    for _, v := range nos {
        assert(t, v)
    }
}

func assert(t *testing.T, o *Object) {
    if o.Num != 1 && o.Num != 2 {
        t.Error("o.Num not 1 or 2, but", o.Num)
    }
    for _, v := range o.Children {
        assert(t, v)
    }
}
@rsc
Copy link
Contributor

rsc commented Feb 14, 2012

Comment 1:

Does look like a bug: the only difference I see between the commented-out
code and the not-working code is that the former uses []Object instead of []*Object.
There are no nil pointers being transmitted as part of a slice (but there are nil
slices).

Labels changed: added priority-go1, go1-must, removed priority-triage.

Owner changed to @robpike.

Status changed to Accepted.

@patrickmn
Copy link
Author

Comment 2:

The strange thing is that the decoding of the []*Object will actually work if you
uncomment the first block (when it has decoded/registered in some Gob global an []Object
previously.)
I figured it would be due to an []Object being gob.Register'ed first, but doing that did
not have the same effect.

@robpike
Copy link
Contributor

robpike commented Feb 17, 2012

Comment 3:

Nice bug. Thanks for the excellent simple example.
Fix out for review.

Status changed to Started.

@patrickmn
Copy link
Author

Comment 4:

Most welcome.

@robpike
Copy link
Contributor

robpike commented Feb 18, 2012

Comment 5:

This issue was closed by revision 793f6f3.

Status changed to Fixed.

@rsc rsc added this to the Go1 milestone Apr 10, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
@rsc rsc unassigned robpike Jun 22, 2022
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants