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: (or maybe time.Time): unexplained error with time.Time value #4647

Closed
robpike opened this issue Jan 11, 2013 · 4 comments
Closed
Milestone

Comments

@robpike
Copy link
Contributor

robpike commented Jan 11, 2013

http://play.golang.org/p/cNlOycuLzl is this:

package main

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

type Update struct {
    Time        time.Time   // ***  Note1 : Works if change from time.Time -> int ***//
}

type Time struct {
    T   *time.Time
}

type PC struct {
    Id            int64 
    Update []Update  // ***  Note2 : Works if comment out one of  Update or LastUpdate ***//
    LastUpdate    Time 
}

func main() {
    buf := new(bytes.Buffer)
    enc := gob.NewEncoder(buf)
    var err error
    if err = enc.Encode(PC{}); err != nil {
        println("A", err.Error())
        return
    }
    dec := gob.NewDecoder(bytes.NewBuffer(buf.Bytes()))
    if err = dec.Decode(new(PC)); err != nil {
        println("B", err.Error())
        return
    }
}

It prints "B extra data in buffer. Removing either of the time.Time values from the
struct or replacing them with ints clears up the error. Something is awry with gots and
time.
@kylelemons
Copy link
Contributor

Comment 1:

It doesn't seem to be related to time.  It seems to be related to two
GobEncoder/GobDecoders in the same value where one is a pointer and the other isn't:
package main
import (
    "bytes"
    "encoding/gob"
)
type T struct{}
func (T) GobEncode() ([]byte, error) {
    return []byte{0xDE, 0xAE, 0xAD, 0xBE, 0xEF}, nil
}
func (T) GobDecode([]byte) error {
    return nil
}
type PC struct {
    A     T
    B *T
}
func main() {
    buf := new(bytes.Buffer)
    enc := gob.NewEncoder(buf)
    var err error
    if err = enc.Encode(PC{}); err != nil {
        println("A", err.Error())
        return
    }
    dec := gob.NewDecoder(bytes.NewBuffer(buf.Bytes()))
    if err = dec.Decode(new(PC)); err != nil {
        println("B", err.Error())
        return
    }
}
http://play.golang.org/p/7MfiN4ToAZ

@kortschak
Copy link
Contributor

Comment 2:

It looks like the arrangement of pointer/non-pointer fields makes a difference. If the
pointer field is first, there is no problem, in other positions the bug appears.

@kylelemons
Copy link
Contributor

Comment 3:

Dan is correct.  It appears to happen because GobEncoders are treated specially and as
such, the *T is encoded immediately, despite the T having already been encoded.  The
"extra data in buffer" error is actually masking the "gob: duplicate type received"
error (which we might also want to address).
I don't know if this is the proper fix, but it makes my test pass:
https://golang.org/cl/7085051

@adg
Copy link
Contributor

adg commented Jan 14, 2013

Comment 4:

This issue was closed by revision bc1152a.

Status changed to Fixed.

@rsc rsc added this to the Go1.1 milestone Apr 14, 2015
@rsc rsc removed the go1.1 label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
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

6 participants