Published on

How to Hash a Struct in Go

Authors

Being able to hash a struct is useful. For example, you may want to have a map that uses a struct's hash as the key. I found a few libraries that do this but I also came across the official sha256 class. My requirements were fairly straightforward and generally, I prefer using standard libraries over external libraries if I have the option.

I looked more into using the standard library. This library looked ideal except that it had no examples of how to SHA a struct.

After a bit of searching, I came across this answer.

Based on all this I came up with the following method to sha256 a struct or anything actually:

import "crypto/sha256"

func AsSha256(o interface{}) string {
    h := sha256.New()
    h.Write([]byte(fmt.Sprintf("%v", o)))

    return fmt.Sprintf("%x", h.Sum(nil))
}

To see how this works you can try out the below code which is also available at this play ground:

package main

import (
    "crypto/sha256"
    "fmt"
)

type Person struct {
    Name    string
    Surname string
    Age     int
}

func asSha256(o interface{}) string {
    h := sha256.New()
    h.Write([]byte(fmt.Sprintf("%v", o)))

    return fmt.Sprintf("%x", h.Sum(nil))
}

func main() {
    person1 := Person{
        Name:    "John",
        Surname: "Smith",
        Age:     18,
    }
    fmt.Println("------------- Person1's hash")
    fmt.Println(asSha256(person1))

    person2 := Person{
        Name:    "John",
        Surname: "Smith",
        Age:     22,
    }
    fmt.Println("------------- Person2's hash")
    fmt.Println(asSha256(person2))
}

This outputs:

------------- Person1's hash
f20fe06d96e179073fc3eebac62d7a2edf3164f0c50524d82c0c6390013bbc4a
------------- Person2's hash
acab53a42218b1ddee807fb68ecae135d1f3b046c12a4db4bf6d36fd790f6c6a

Program exited.

Some caveat's with this approach:

  • It is tied to an objects String method.
    • As a result changing this will result in you getting a different hash - even something as small as adding or removing a space.
    • You also need to make sure that the String method includes all the fields that should be SHA'd - leaving some key fields out will result in collisions.
      • For example if my Person String method only output Age there would be a collision for people who are the same age.
  • I have not tested how performant it is - you would need to do this yourself if performance is an issue for your app.