如何告诉Golang Gob编码器可以序列化包含未公开字段的结构体中的结构体

6

我认为这是使用Gob序列化的合法用例。然而,enc.Encode返回了一个错误,因为Something没有导出的字段。请注意,我只是序列化包含导出字段的Composed而不是直接序列化Something

我找到的唯一解决方法是向Something添加一个公开值Dummy。这很丑陋。有更优雅的解决方案吗?

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)
    }
}

2
FYI:在Go存储库https://github.com/golang/go/issues/5819中有一个未解决的问题。 - fl9
@ThunderCat 有趣的是,就在你发表评论的时候,我正在尝试你的第二个解决方案。信不信由你,我发现它更加简洁(因为它仅限于代码,不会用虚假数据污染流)。 - Franck Jeannin
@ThunderCat 第一个有太多样板代码,第二个是最不丑陋的(空数组真的安全吗?还是应该是一个空数组?) - Franck Jeannin
2个回答

4
以下是与问题中提出的解决方案不同的一些解决方法。
不要使用嵌入。
type Composed struct {
    something       Something
    DataToSerialize int
}

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

示例代码

实现GobDecoderGobEncoder接口。

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

playground example


第一种解决方案不切实际,因为某个东西可能有几十种方法。 - Franck Jeannin
@FranckJeannin 为什么第一个解决方案不切实际?即使某些值得序列化的东西拥有数十种方法:只需将它们转发即可。这完全不是什么高深的技术。 - Volker
1
@Volker,问题在于解决方案1会添加指数级的代码。每次向Something添加一个方法,都需要将其转发到嵌入Something的所有结构体中。如果您认为解决方案2太过高深,我建议使用解决方案0:向Something添加一个虚拟成员(已导出)。这只需要一行代码,无论您嵌入Something多少次。 - Franck Jeannin

0
据我所知,添加GobDecode和GobEncode函数只能使编码器避免错误,但不能使其正常工作。 如果我添加一个解码操作,似乎无法将DataToSerialize项返回为我编码的值。 Playground example

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接