0

My goal is to have a linked data structure, this is, a struct with a reference to another struct, and so on, so I can encode it into my file system, and whenever I need it, decode it, so I restore the whole linked structure, with the same content.

Example:

I have these linked structures:

type A struct {
    b *B
}

type B struct {
    c []C
}

type C interface{}

I initialize them this way:

var c0 C = "foo"
var c1 C = "bar"

var b *B = &B{}
b.c = make([]C, 2)
b.c[0] = c0
b.c[1] = c1

var a A = A{}
a.b = b

fmt.Println(a)
// {$b_address}

fmt.Println(a.b)
// {[c0_address,c1_address]}

fmt.Println(a.b.c[0])
// foo

fmt.Println(a.b.c[1])
// bar

I would like to know how to encode A, having it persisted into a file, so I can decode it getting the same result. Addresses are not important, but the content is. I've tried it with encoding/gob, with no success:

// encode
f, err := os.Create("data.gob")

if err != nil {
    fmt.Println(err)
    os.Exit(1)
}

enc := gob.NewEncoder(f)
enc.Encode(a)

f.Close()

// decode

var a1 A
f, err = os.Open("data.gob")

if err != nil {
    fmt.Println(1, err)
    os.Exit(1)
}

dec := gob.NewDecoder(f)
dec.Decode(&a1)
if err != nil {
    fmt.Println(2, err)
    os.Exit(1)
}
f.Close()

fmt.Println(a1)
// {<nil>}
// expected {$b_address}

Full example: http://play.golang.org/p/2vxHR9BzNy

Is there a way to do this without making the fields public? Is there any existing solution so I don't need to reinvent the wheel?

Fernando Á.
  • 7,295
  • 7
  • 30
  • 32
  • It could be, adding the fields as public made it working. I need to try it in my real world example before marking as resolved. – Fernando Á. Sep 23 '15 at 16:18
  • 2
    It's not about pointers. Your fields are lowercase and thus unexported. – Ainar-G Sep 23 '15 at 16:20
  • 3
    Side note, it is very rare to want to use pointers to an interface as [they're effectively already pointers](http://research.swtch.com/interfaces). This is similar to usually not using pointers to maps or slices. (e.g. I'd use `Field []C` rather than `[]*C` in your struct). – Dave C Sep 23 '15 at 16:23
  • @DaveC thx for the pointer, updated sample code and playground link – Fernando Á. Sep 23 '15 at 16:28
  • @Ainar-G definitely I can't set certain struct fields to public just to satisfy this in my real world case – Fernando Á. Sep 23 '15 at 16:28

2 Answers2

2

Is there a way to do this without making the fields public? Is there any existing solution so I don't need to reinvent the wheel?

Unless you're willing to do this through copying all of your data into types with exported fields when encoding and from them when decoding, no.

If the data is unexported other packages just can't see it. That's why they're called unexported. Packages like encoding/json, encoding/xml, and encoding/gob only operate on exported data for this exact reason.

Ainar-G
  • 34,563
  • 13
  • 93
  • 119
0

The fields have to be exported. Packages that do encoding/serialization ect have no way of seeing the fields otherwise. As long as your fields are exported any of the encoding/ packages will do what you want by default.

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115