6

I believe this is a legitimate use case for Gob serialization. Yet enc.Encode returns an error because Something has no exported field. Note that I’m not serializing Something directly but only Composed that contains exported fields.

The only workaround I’ve found was to add a Dummy (exported) value to Something. This is ugly. Is there a more elegant solution?

https://play.golang.org/p/0pL6BfBb78m

package main

import (
    "bytes"
    "encoding/gob"
)

type Something struct {
    temp int
}

func (*Something) DoSomething() {}

type Composed struct {
    Something
    DataToSerialize int
}

func main() {
    enc := gob.NewEncoder(&bytes.Buffer{})
    err := enc.Encode(Composed{})
    if err != nil {
        panic(err)
    }
}
ain
  • 22,394
  • 3
  • 54
  • 74
Franck Jeannin
  • 6,107
  • 3
  • 21
  • 33
  • 2
    fyi: there is an open issue for this in the Go repository https://github.com/golang/go/issues/5819 – fl9 May 16 '18 at 16:22
  • @ThunderCat Funnily enough I was experimenting with your second solution exactly at the time you wrote your comment. And believe it or not, I find it less ugly (because it’s limited to the code and does not pollute the stream with dummy data) – Franck Jeannin May 16 '18 at 17:01
  • @ThunderCat too much boiler plate for the first one, second one is the least ugly one (is the nil array really safe or should it be an empty array?) – Franck Jeannin May 16 '18 at 17:06

2 Answers2

4

Here are some different workarounds from that proposed in the question.

Don't use embedding.

type Composed struct {
    something       Something
    DataToSerialize int
}

func (c *Composed) DoSomething() { c.something.DoSomething() }

playground example

Implement GobDecoder and GobEncoder

func (*Something) GobDecode([]byte) error     { return nil }
func (Something) GobEncode() ([]byte, error) { return nil, nil }

playground example

Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
  • First solution is not practical, Something could have dozens of methods. – Franck Jeannin May 16 '18 at 17:09
  • @FranckJeannin Why would the first solution be not practical? Even if something worth serializing would ever have dozens of methods: Just forward them. This is the exact opposite of rocket-science. – Volker May 17 '18 at 05:16
  • 1
    @Volker it’s just that solution 1 will add exponentially more code, each time you add a method to Something you need to forward it for all the structs that embed Something. If you find solution 2 too rocket-science, I would suggest solution 0 : add a Dummy (exported) member to Something. It’s exactly one line of code regardless of own many times you embed Something. – Franck Jeannin May 17 '18 at 06:58
0

As far as I can tell the addition of the functions GobDecode and GobEncode only allow the encoder to avoid the error, but don't allow it to work correctly. If I add a Decode operation it doesn't seem to get the DataToSerialize item back with the value I encoded into it.

Playground example