Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

De- and encode interface{} with Gob

Tags:

go

gob

I'm trying to de- and encode a struct which contains a Interface{} as field.

The problem there is, that the encoding works fine, but if I try to decode the data to data the value gets { <nil>}.

It actually works, if I change Data interface{} to Data substring, but this is not a solution for me because I want to cache the results of a query to a database which have different types depending on the query. (e.g. Users or Cookies)

Minimal working example

Source

http://play.golang.org/p/aX7MIfqrWl

package main

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

type Data struct {
    Name string
    Data interface{}
}

type SubType struct {
    Foo string
}

func main() {
    // Encode
    encodeData := Data{
        Name: "FooBar",
        Data: SubType{Foo: "Test"},
    }
    mCache := new(bytes.Buffer)
    encCache := gob.NewEncoder(mCache)
    encCache.Encode(encodeData)

    fmt.Printf("Encoded: ")
    fmt.Println(mCache.Bytes())

    // Decode
    var data Data
    pCache := bytes.NewBuffer(mCache.Bytes())
    decCache := gob.NewDecoder(pCache)
    decCache.Decode(&data)

    fmt.Printf("Decoded: ")
    fmt.Println(data)
}

Outputs

Expected output

Encoded: [37 255 129 3 1 1 4 68 97 116 97 1 255 130 0 1 2 1 4 78 97 109 101 1 12 0 1 4 68 97 116 97 1 255 132 0 0 0 29 255 131 3 1 1 7 83 117 98 84 121 112 101 1 255 132 0 1 1 1 3 70 111 111 1 12 0 0 0 19 255 130 1 6 70 111 111 66 97 114 1 1 4 84 101 115 116 0 0]

Decoded: {FooBar {Test}}

Current Result

Encoded: [37 255 129 3 1 1 4 68 97 116 97 1 255 130 0 1 2 1 4 78 97 109 101 1 12 0 1 4 68 97 116 97 1 255 132 0 0 0 29 255 131 3 1 1 7 83 117 98 84 121 112 101 1 255 132 0 1 1 1 3 70 111 111 1 12 0 0 0 19 255 130 1 6 70 111 111 66 97 114 1 1 4 84 101 115 116 0 0]

Decoded: { }

like image 555
Testuser Avatar asked Jan 02 '13 11:01

Testuser


People also ask

What is encoding gob?

Gob is a serialisation technique specific to Go. It is designed to encode Go data types specifically and does not at present have support for or by any other programming language. Gob packet is used to manage gob stream. It can send binary data stream between encoder (transmitter) and decoder (receiver).

How do I use gob?

To use gobs, create an Encoder and present it with a series of data items as values or addresses that can be dereferenced to values. The Encoder makes sure all type information is sent before it is needed. At the receive side, a Decoder retrieves values from the encoded stream and unpacks them into local variables.


1 Answers

The problem is that in your code, there is an error when executing encCache.Encode(encodeData) but since you don't check for error, you don't realize that. The output is blank because encodedData fails to get encoded properly.

If you add error checking,

err := enc.Encode(encodeData)
if err != nil {
    log.Fatal("encode error:", err)
}

Then you'd see something like

2013/03/09 17:57:23 encode error:gob: type not registered for interface: main.SubType

If you add one line to your original code before enc.Encode(encodeData),

gob.Register(SubType{})

Then you get expected output.

Decoded: {FooBar {Test}}

See http://play.golang.org/p/xt4zNyPZ2W

like image 179
Dmitri Shuralyov Avatar answered Sep 30 '22 04:09

Dmitri Shuralyov