Go 结构中的唯一哈希

Go 结构中的唯一哈希,go,struct,hash,Go,Struct,Hash,我想从结构数组中生成一个唯一的散列。顺序可能不同,但值相同 例如: type MyStruct struct { ID string Parameters map[string]interface{} } arr:= []MyStruct{MyStruct{ID: "test", Parameters: map[string]interface{}{"key": true, "key2": "value"} }, MyStruct{ID: "test2", Parameters:

我想从结构数组中生成一个唯一的散列。顺序可能不同,但值相同

例如:

type MyStruct struct {
   ID string
   Parameters map[string]interface{}
}

arr:= []MyStruct{MyStruct{ID: "test", Parameters: map[string]interface{}{"key": true, "key2": "value"} }, MyStruct{ID: "test2", Parameters: map[string]interface{}{"key2": "value", "key": true} }}
//The order is different even inside the Parameters fields

arr:= []MyStruct{MyStruct{ID: "test2", Parameters: map[string]interface{}{"key2": "value", "key": true} },MyStruct{ID: "test", Parameters: map[string]interface{}{"key": true, "key2": "value"} }}
在这两种情况下,散列应该是相同的,因为结构中的值是相同的


编辑:其基本思想是为缓存生成唯一的哈希!我想合并每个结构的散列

可以通过将数组序列化为字节数组,然后计算字节数组的md5和来完成此操作。由于md5和是字节的散列,因此顺序无关紧要

要序列化数组的每个元素,可以使用
json.Marshal
,它将适用于任何类型的
struct

哈希函数的外观如下所示:

func Hash(arr []SomeStruct) [16]byte {
    arrBytes := []byte{}
    for _, item := range arr {
        jsonBytes, _ := json.Marshal(item)
        arrBytes = append(arrBytes, jsonBytes...)
    }
    return md5.Sum(arrBytes)
}
您可以运行工作示例程序

这将输出:

Hash1: d065fee603fdcf75115204ec65310e1c
Hash2: d065fee603fdcf75115204ec65310e1c

Feng说得有道理,接受的答案不起作用,不仅因为结构中没有导出字段,还因为MD5哈希的方式具有顺序意义,请参阅

不确定是否有效,但我通过使用
encoding/gob
bytes
将切片作为字节传递,并在
Compare
中使用表示散列的
bytes,实现了一些功能


也许我能帮你。它始终对结构进行散列,但可以与切片和数组一起使用。

映射按设计顺序排列。使用数组来保持秩序。不清楚你在问什么。是要散列结构的切片(而不是数组),还是散列单个结构?最好问问为什么。是否要检查内容是否相等(无论顺序如何),还是要进行校验和?请澄清。基本上,这个想法是生成一个用于缓存的唯一哈希!我想合并每个结构的散列!因此,您需要包含无序数据结构的复杂数据结构的散列。实现这一点的最快方法是序列化数据(对字段进行排序),并使用足够大的值对其进行散列,以避免冲突。然而,我严重怀疑您的缓存需要在整个数据上,它通常在非常有限的子集上(例如:有人查询一个唯一的ID并获取大量数据。这意味着您的缓存密钥是唯一的ID,而不是数据)。很好,我在寻找这个:“既然md5和是字节的哈希和,顺序就不重要了。”也许我需要开始阅读更多关于散列算法的内容:)因为SomeStruct中没有导出字段,所以封送结果是相同的。如果将param1和param1更改为大写,则哈希结果将不同。如前所述,这个答案完全错误。要使类似的东西正常工作,数据的顺序必须相同,因此您需要首先对结构进行排序。要进一步说明这有多么错误,请在调试器中运行它,并查看
jsonBytes
==“{}”。您也可以对
jsonBytes
使用print语句@MarcoTalento请将此作为可接受的答案删除。是否有人可以确认JSON封送器/编码器保证是确定性的,即使是在不同版本之间?从现在起一年后产生的哈希值是否会相同(未来版本的Go)?请阅读并改进您的答案。链接不是有效的答案。
Hash1: d065fee603fdcf75115204ec65310e1c
Hash2: d065fee603fdcf75115204ec65310e1c
package main

import (
    "bytes"
    "encoding/gob"
    "fmt"
)

type S struct {
    K1 string
    K2 int
}

func main() {
    sa := []S{{ K1: "foo", K2: 1}, {K1: "bar", K2: 2}, {K1: "baz", K2: 3,}}
    sb := []S{{ K1: "baz", K2: 3}, {K1: "bar", K2: 2}, {K1: "foo", K2: 1,}}
    sc := []S{}

    a := Hash(sa)
    b := Hash(sb)
    c := Hash(sc)

    fmt.Println(Compare(a, b))
    fmt.Println(Compare(a, c))
}

func Compare(a, b []byte) bool {
    a = append(a, b...)
    c := 0
    for _, x := range a {
        c ^= int(x)
    }
    return c == 0
}

func Hash(s []S) []byte {
    var b bytes.Buffer
    gob.NewEncoder(&b).Encode(s)
    return b.Bytes()
}