一些目标看起来像:
- 散列任何内容 -通过散列开箱即用的东西来使其易于使用
- 缓存哈希 -使更新只是重新 哈希 他们需要的内容
- 习惯用法 -与其他Go代码完美匹配
我认为您可以使用类似于内置
encoding/gob或
encoding/jsondo之类的序列化工具的方式大致上对哈希进行攻击,这是三管齐下的:如果类型实现了(对于JSON而言
MarshalJSON),则使用特殊方法;对于基本类型使用类型开关,然后使用反射回退到令人讨厌的默认情况。这是一个API草图,它提供了哈希缓存的帮助器,并允许类型实现
Hash或不实现:
package merkletype HashVal uint64const 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() }}


