【发布时间】:2014-08-26 14:06:53
【问题描述】:
我目前正在尝试在 Go 中实现一个默克尔树数据结构。基本上,我的最终目标是存储一小组结构化数据(最大 10MB),并允许这个“数据库”轻松地与分布在网络上的其他节点同步(参见相关资料)。 由于没有类型检查,我已经在 Node 中合理有效地实现了这一点。这就是 Go 的问题所在,我想利用 Go 的编译时类型检查,但我也希望有一个可以与任何提供的树一起使用的库。
简而言之,我想将结构用作 merkle 节点,并且我想拥有一个嵌入所有类型的 Merkle.Update() 方法。我试图避免为每个结构写一个Update()(尽管我知道这可能是唯一/最好的方法)。
我的想法是使用嵌入式类型:
//library
type Merkle struct {
Initialised bool
Container interface{} //in example this references foo
Fields []reflect.Type
//... other merkle state
}
//Merkle methods... Update()... etc...
//userland
type Foo struct {
Merkle
A int
B bool
C string
D map[string]*Bazz
E []*Bar
}
type Bazz struct {
Merkle
S int
T int
U int
}
type Bar struct {
Merkle
X int
Y int
Z int
}
在此示例中,Foo 将是根,其中将包含 Bazzs 和 Bars。这种关系可以通过反映类型来推断。问题是用法:
foo := &Foo{
A: 42,
B: true,
C: "foo",
D: map[string]*Bazz{
"b1": &Bazz{},
"b2": &Bazz{},
},
E: []*Bar{
&Bar{},
&Bar{},
&Bar{},
},
}
merkle.Init(foo)
foo.Hash //Initial hash => abc...
foo.A = 35
foo.E = append(foo.E, &Bar{})
foo.Update()
foo.Hash //Updated hash => def...
我认为我们需要merkle.Init(foo),因为foo.Init() 实际上是foo.Merkle.Init(),并且无法反映foo。未初始化的Bars 和Bazzs 可以被父foo.Update() 检测和初始化。一些反思是可以接受的,因为目前正确性比性能更重要。
另一个问题是,当我们Update() 一个节点时,所有结构字段(子节点)也需要为Update()d(重新散列),因为我们不确定发生了什么变化。我们可以使用foo.SetInt("A", 35) 来实现自动更新,但是我们会丢失编译时类型检查。
这会被认为是惯用的 Go 吗?如果没有,如何改进?谁能想到另一种方法来将数据集存储在内存中(用于快速读取)并进行简洁的数据集比较(用于通过网络进行有效的增量传输)? 编辑:还有一个元问题:问这类问题的最佳地点在哪里,StackOverflow、Reddit 还是 go-nuts?最初发布在reddit 没有答案:(
【问题讨论】:
-
你需要在某个地方提供完整的代码,play.golang.com 或者如果它是多个文件,把它放在 github 上。
-
好的,我会发布我所拥有的(和一个测试用例),尽管它主要只是 API 原型设计。在我承诺实施这一点之前,我想我会问我是否朝着正确的方向前进。
标签: data-structures go