Which design pattern to use to store streams of objects of different types to disk in go?

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

Which design pattern to use to store streams of objects of different types to disk in go?

问题

考虑一个将不同类型的对象流保存到磁盘的函数:

func Save(fill func(c chan BaseType), file string) {}

这个函数在代码中以以下方式使用:

// 这里有不同的数据结构 data1, data2, ...
// 需要保存到磁盘
Save(
  func(c chan BaseType) {
    // SaveChildren1 根据 data1 数据结构生成 Child1 类型的对象
    SaveChildren1(c, data1) 
  },
  filename1)

Save(
  func(c chan BaseType) {
    // SaveChildren2 根据 data2 数据结构生成 Child2 类型的对象
    SaveChildren2(c, data2)
  },
  filename2)

以此类推。有很多不同的子类型,每个子类型都需要自己的生成器函数,比如 SaveChildren1、SaveChildren2 等。这些函数实际上会填充通道(channel)中的对象。

问题是,你会如何重构这些“绑定器”——将 SaveChildren(一个带有两个参数的函数)转换为一个带有一个参数的函数?目前这段代码看起来不像是符合 Go 语言风格的良好代码。

英文:

Consider a function that saves streams of objects of different types to disk:

func Save(fill func(c chan BaseType), file string) {}

This function is used in the following way throughout the code:

// Here we've got different data structures data1, data2, ...
// that must be stored to disk
Save(
  func(c chan BaseType) {
    // SaveChildren1 generates objects of type Child1 based
    // on the data1 data structure
    SaveChildren1(c, data1) 
  },
  filename1)

Save(
  func(c chan BaseType) {
    // SaveChildren2 generates objects of type Child2 based
    // on the data2 data structure
    SaveChildren2(c, data2)
  },
  filename2)

And so on. There are a lot of different child types and each requires it's own generator -- a function SaveChildren1, SaveChildren2 etc. These functions actually fill the channels with objects.

The question is how would you refactor these "binders" -- the functions that transform SaveChildren (a function of 2 args) into a function of 1 argument? Currently this code doesn't look like a well written go-style code.

答案1

得分: 3

gob包似乎是解决您问题的好方法。Go博客上有一篇很棒的文章,解释了如何以及为什么要使用gob包。以下是其中的一小段摘录:

gob包在设计时考虑了许多目标。

首先,最明显的是,它必须非常容易使用。因为Go具有反射,所以不需要单独的接口定义语言或“协议编译器”。数据结构本身就足够让该包知道如何进行编码和解码。另一方面,这种方法意味着gob在与其他语言一起使用时可能效果不佳,但这没关系:gob是面向Go的。

效率也很重要。以XML和JSON为代表的文本表示法在高效通信网络的核心位置太慢了。需要一种二进制编码。

Gob流必须是自描述的。每个从开头读取的gob流都包含足够的信息,使得完全不知道其内容的代理程序可以解析整个流。这个特性意味着,即使在很久之后,您也始终能够解码存储在文件中的gob流,即使您已经忘记了它表示的数据。

文章的后面还有一个示例,展示了gob包的易用性和多功能性。

英文:

The gob package seems like a good solution for your problem. There is a great article on the Go blog that explains how and why. A short excerpt:

> The gob package was designed with a number of goals in mind.
>
> First, and most obvious, it had to be very easy to use. First, because
> Go has reflection, there is no need for a separate interface
> definition language or "protocol compiler". The data structure itself
> is all the package should need to figure out how to encode and decode
> it. On the other hand, this approach means that gobs will never work
> as well with other languages, but that's OK: gobs are unashamedly
> Go-centric.
>
> Efficiency is also important. Textual representations, exemplified by
> XML and JSON, are too slow to put at the center of an efficient
> communications network. A binary encoding is necessary.
>
> Gob streams must be self-describing. Each gob stream, read from the
> beginning, contains sufficient information that the entire stream can
> be parsed by an agent that knows nothing a priori about its contents.
> This property means that you will always be able to decode a gob
> stream stored in a file, even long after you've forgotten what data it
> represents.

Further down the article is an example that shows how easy it is to use and how versatile it is.

huangapple
  • 本文由 发表于 2015年5月5日 07:02:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/30041461.html
匿名

发表评论

匿名网友

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

确定