我目前正在尝试在Go中实现Merkle-
tree数据结构。基本上,我的最终目标是存储一小组结构化数据(最大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
将是根,其中将包含Bazz
s和Bar
s。可以通过思考类型来推断这种关系。问题是用法:
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
。未初始化的Bar
s和Bazz
s可以由父级检测并初始化foo.Update()
。可以接受一些反思,因为当前的正确性比性能更重要。另一个问题是,当我们Update()
成为一个节点时,Update()
由于我们不确定要更改的内容,因此所有结构字段(子节点)也都需要被删除(重新映射)。我们可以foo.SetInt("A", 35)
实现自动更新,尽管那样我们会丢失编译时的类型检查。
会认为这是惯用的Go吗?如果没有,如何改善?谁能想到一种简洁的数据集比较(用于通过网络进行有效增量传输)将数据集存储在内存中(用于快速读取)的替代方法吗?编辑:还有一个元问题:问此类问题的最佳地点是StackOverflow,Reddit或螺母?最初发布在reddit上没有答案:(
一些目标看起来像:
我认为您可以使用类似于内置encoding/gob
或encoding/json
do之类的序列化工具的方式大致上对哈希进行攻击,这是三管齐下的:如果类型实现了(对于JSON而言MarshalJSON
),则使用特殊方法;对于基本类型使用类型开关,然后使用反射回退到令人讨厌的默认情况。这是一个API草图,它提供了哈希缓存的帮助器,并允许类型实现Hash
或不实现:
package merkle
type HashVal uint64
const MissingHash HashVal = 0
// Hasher provides a custom hash implementation for a type. Not
// everything needs to implement it, but doing so can speed
// updates.
type Hasher interface {
Hash() HashVal
}
// HashCacher is the interface for items that cache a hash value.
// Normally implemented by embedding HashCache.
type HashCacher interface {
CachedHash() *HashVal
}
// HashCache implements HashCacher; it's meant to be embedded in your
// structs to make updating hash trees more efficient.
type HashCache struct {
h HashVal
}
// CachedHash implements HashCacher.
func (h *HashCache) CachedHash() *HashVal {
return &h.h
}
// Hash returns something's hash, using a cached hash or Hash() method if
// available.
func Hash(i interface{}) HashVal {
if hashCacher, ok := i.(HashCacher); ok {
if cached := *hashCacher.CachedHash(); cached != MissingHash {
return cached
}
}
switch i := i.(type) {
case Hasher:
return i.Hash()
case uint64:
return HashVal(i * 8675309) // or, you know, use a real hash
case []byte:
// CRC the bytes, say
return 0xdeadbeef
default:
return 0xdeadbeef
// terrible slow recursive case using reflection
// like: iterate fields using reflect, then hash each
}
// instead of panic()ing here, you could live a little
// dangerously and declare that changes to unhashable
// types don't invalidate the tree
panic("unhashable type passed to Hash()")
}
// Item is a node in the Merkle tree, which must know how to find its
// parent Item (the root node should return nil) and should usually
// embed HashCache for efficient updates. To avoid using reflection,
// Items might benefit from being Hashers as well.
type Item interface {
Parent() Item
HashCacher
}
// Update updates the chain of items between i and the root, given the
// leaf node that may have been changed.
func Update(i Item) {
for i != nil {
cached := i.CachedHash()
*cached = MissingHash // invalidate
*cached = Hash(i)
i = i.Parent()
}
}
我正试图用Java编写一个非常简单的merkle树实现。 我使用比特币区块链上方框170中的TXID值作为参考,因此我可以看到正确的结果。 与该块对应的TXID如下所示: 据我了解,比特币的merkle树实现方式如下: 将块中的事务拆分为成对的事务 有一个警告是: 我的代码在一个开关语句中,它看起来像这样: 我编写的swapEndianness方法不是真正的“字节级”交换,而是更改字符串的顺序,如
本文向大家介绍使用go实现常见的数据结构,包括了使用go实现常见的数据结构的使用技巧和注意事项,需要的朋友参考一下 1 golang常见数据结构实现 1.1 链表 举单链表的例子,双向链表同理只是多了pre指针。 定义单链表结构: 构造链表及打印链表: 1.2 可变数组 可变数组在各种语言中都非常常用,在golang中,可变数组语言本身已经实现,就是我们的切片slice。 1.3 栈和队列 1.3
树表示由边连接的节点。 我们将具体讨论二叉树或二叉搜索树。 二叉树是用于数据存储目的的特殊数据结构。 二叉树具有特殊条件,即每个节点最多可以有两个子节点。 二叉树具有有序数组和链表的优点,因为搜索与排序数组一样快,插入或删除操作与链表一样快。 重要条款 以下是关于树的重要术语。 Path - 路径是指沿树边缘的节点序列。 Root - 树顶部的节点称为root。 每个树只有一个根,从根节点到任何节
问题内容: 我有传入的有效负载,无法更改。 我需要获取“数据”的第一个索引并创建一个新的JSON对象,如下所示… 然后从中构建一个,其数据结构的长度为5k个“主机”。我能够将其映射到结构,但需要首先将其转换为这种格式。我了解如何解组JSON,但前提是可以将有效负载转换为上述格式。 问题答案: 我不确定我是否了解您的需求。 可能是这样的事情?可能需要做一些工作,例如使指向结构的指针切片而不是结构的切
本文向大家介绍Go语言实现的树形结构数据比较算法实例,包括了Go语言实现的树形结构数据比较算法实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Go语言实现的树形结构数据比较算法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的Go语言程序设计有所帮助。
本章讲解如何使用 Rust 进行一些常用数据结构的实现。实现的代码仅作示例用,并不一定十分高效。真正使用的时候,请使用标准库或第三方成熟库中的数据结构。