diff --git a/src/pkg/gob/encoder_test.go b/src/pkg/gob/encoder_test.go index 91d85bb7ad6..e5fc80837ee 100644 --- a/src/pkg/gob/encoder_test.go +++ b/src/pkg/gob/encoder_test.go @@ -354,3 +354,32 @@ func TestStructNonStruct(t *testing.T) { t.Error("for non-struct/struct expected type error; got", err) } } + +type interfaceIndirectTestI interface { + F() bool +} + +type interfaceIndirectTestT struct{} + +func (this *interfaceIndirectTestT) F() bool { + return true +} + +// A version of a bug reported on golang-nuts. Also tests top-level +// slice of interfaces. The issue was registering *T caused T to be +// stored as the concrete type. +func TestInterfaceIndirect(t *testing.T) { + Register(&interfaceIndirectTestT{}) + b := new(bytes.Buffer) + w := []interfaceIndirectTestI{&interfaceIndirectTestT{}} + err := NewEncoder(b).Encode(w) + if err != nil { + t.Fatal("encode error:", err) + } + + var r []interfaceIndirectTestI + err = NewDecoder(b).Decode(&r) + if err != nil { + t.Fatal("decode error:", err) + } +} diff --git a/src/pkg/gob/type.go b/src/pkg/gob/type.go index d68c8773cfd..1c2b2027ef1 100644 --- a/src/pkg/gob/type.go +++ b/src/pkg/gob/type.go @@ -470,7 +470,9 @@ func RegisterName(name string, value interface{}) { if n, ok := concreteTypeToName[rt]; ok && n != name { panic("gob: registering duplicate names for " + rt.String()) } - nameToConcreteType[name] = rt + // Store the name and type provided by the user.... + nameToConcreteType[name] = reflect.Typeof(value) + // but the flattened type in the type table, since that's what decode needs. concreteTypeToName[rt] = name }