Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unique Hash from struct

Tags:

struct

hash

go

I would like to generate a unique hash from an array of structs. The order might be different but the values are the same.

Example:

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"} }}

In both cases the hash should be the same since the values inside the structs are the same.

EDIT: Basically the idea is to generate a unique hash for caching! I want to combine the individual hash of each struct!

like image 625
Marco Talento Avatar asked Jan 14 '18 19:01

Marco Talento


2 Answers

Feng has a point, the accepted answer doesn't work not only because there are no exported fields in the struct, but also the fact that the way MD5 hashes does have order significance, see RFC 1321 3.4.

Not sure on efficacy, but I've got something working by passing in the slice as bytes using encoding/gob and bytes representing a hash to use in Compare.

Playground

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()
}
like image 158
woat Avatar answered Nov 07 '22 04:11

woat


Maybe https://github.com/mitchellh/hashstructure could help you. It consistently hashes struct but can be used with slices and arrays.

like image 30
M C Avatar answered Nov 07 '22 04:11

M C