如何在Go中持久化或编码一个链式数据结构?

huangapple go评论79阅读模式
英文:

How to persist or encode a linked data structure in Go?

问题

我的目标是拥有一个链接数据结构,也就是一个包含对另一个结构的引用的结构,以此类推,这样我就可以将其编码到我的文件系统中,每当我需要时,解码它,以恢复整个链接结构,具有相同的内容。

示例:

我有以下链接结构:

type A struct {
	b *B
}

type B struct {
	c []C
}

type C interface{}

我这样初始化它们:

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

我想知道如何编码A,将其持久化到文件中,以便我可以解码它并获得相同的结果。地址并不重要,但内容是重要的。我尝试过使用encoding/gob,但没有成功:

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

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

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

f.Close()

// 解码

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>}
// 期望 {$b_address}

完整示例:http://play.golang.org/p/2vxHR9BzNy

有没有一种方法可以在不将字段设为公共的情况下实现这一点?是否有任何现有的解决方案,以免重复造轮子?

英文:

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 = &quot;foo&quot;
var c1 C = &quot;bar&quot;

var b *B = &amp;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(&quot;data.gob&quot;)

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(&quot;data.gob&quot;)

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

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

fmt.Println(a1)
// {&lt;nil&gt;}
// 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?

答案1

得分: 2

有没有一种方法可以在不将字段公开的情况下完成这个操作?有没有任何现有的解决方案,这样我就不需要重新发明轮子了?

除非你愿意通过在编码时将所有数据复制到具有导出字段的类型中,然后在解码时从这些类型中获取数据,否则是不可能的。

如果数据是未导出的,其他包就无法看到它。这就是为什么它们被称为未导出的。像encoding/jsonencoding/xmlencoding/gob这样的包之所以只操作导出的数据,就是因为这个原因。

英文:

>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.

答案2

得分: 0

字段必须被导出。进行编码/序列化等操作的包无法直接访问这些字段。只要你的字段是导出的,任何encoding/包都会默认执行你想要的操作。

英文:

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.

huangapple
  • 本文由 发表于 2015年9月24日 00:09:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/32744506.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定