12

I have read the documentation of ( gob) and I have some problems :

Now I know how to encode structure and decode like that:

func main() {
    s1 := &S{
        Field1: "Hello Gob",
        Field2: 999,
    }
    log.Println("Original value:", s1)
    buf := new(bytes.Buffer)
    err := gob.NewEncoder(buf).Encode(s1)
    if err != nil {
        log.Println("Encode:", err)
        return
    }

    s2 := &S{}
    err = gob.NewDecoder(buf).Decode(s2)
    if err != nil {
        log.Println("Decode:", err)
        return
    }
    log.Println("Decoded value:", s2)
}

But I don't know the purpose of this method gob.Register() can someone explain to me when to use it and why?

mergenchik
  • 1,129
  • 16
  • 27

3 Answers3

15

If you're dealing with concrete types (structs) only, you don't really need it. Once you're dealing with interfaces you must register your concrete type first.

For example, let's assume we have these struct and interface (the struct implements the interface):

type Getter interface {
    Get() string
}


type Foo struct {
    Bar string
}

func (f Foo)Get() string {
    return f.Bar
}

To send a Foo over gob as a Getter and decode it back, we must first call

gob.Register(Foo{})

So the flow would be:

// init and register
buf := bytes.NewBuffer(nil)
gob.Register(Foo{})    


// create a getter of Foo
g := Getter(Foo{"wazzup"})

// encode
enc := gob.NewEncoder(buf)
enc.Encode(&g)

// decode
dec := gob.NewDecoder(buf)
var gg Getter
if err := dec.Decode(&gg); err != nil {
    panic(err)
}

Now try removing the Register and this won't work because gob wouldn't know how to map things back to their appropriate type.

Not_a_Golfer
  • 47,012
  • 14
  • 126
  • 92
0

As http://golang.org/pkg/encoding/gob/#Register said:

Only types that will be transferred as implementations of interface values need to be registered.

So it doesn't needed by your demo.

RoninDev
  • 5,446
  • 3
  • 23
  • 37
yee
  • 1,975
  • 1
  • 15
  • 14
0

If you want to encode / decode a map[string]interface{}, since the field of the map is enclosed as interface type, then we need to register the specific type before.


package main

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

type SomeStruct struct {
    Text string
}

func main() {
    var bytes bytes.Buffer

    // Remove one of these, then the decoding will produce error
    gob.Register(SomeStruct{})
    gob.Register([]interface{}{})
    gob.Register([]SomeStruct{})
    gob.Register(map[string]SomeStruct{})

    writer := gob.NewEncoder(&bytes)

    err := writer.Encode(map[string]interface{}{
        "SomeStruct": SomeStruct{"Halo"},
        "SomeSlice":  []interface{}{},
        "SomeSliceStruct": []SomeStruct{
            {
                Text: "SomeText",
            },
        },
        "SomeMapStruct": map[string]SomeStruct{
            "S": {"Test"},
        },
    })
    if err != nil {
        log.Fatalf("Error on encode process: %v\n", err)
        return
    }

    reader := gob.NewDecoder(&bytes)
    var aMap map[string]interface{}
    err = reader.Decode(&aMap)
    if err != nil {
        log.Fatalf("Error on decode process: %v\n", err)
        return
    }

    fmt.Printf("Decode is successful: %+v\n", aMap)
}

mamaz
  • 64
  • 4