structhash

package module
v0.0.0-...-e1b16c1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2020 License: ISC Imports: 8 Imported by: 84

README

structhash GoDoc Build Status

structhash is a Go library for generating hash strings of arbitrary data structures.

Features

  • fields may be ignored or renamed (like in json.Marshal, but using different struct tag)
  • fields may be serialized
  • fields may be versioned
  • fields order in struct doesn't matter (unlike json.Marshal)
  • nil values are treated equally to zero values

Installation

Standard go get:

$ go get github.com/cnf/structhash

Documentation

For usage and examples see the Godoc.

Quick start

package main

import (
    "fmt"
    "crypto/md5"
    "crypto/sha1"
    "github.com/cnf/structhash"
)

type S struct {
    Str string
    Num int
}

func main() {
    s := S{"hello", 123}

    hash, err := structhash.Hash(s, 1)
    if err != nil {
        panic(err)
    }
    fmt.Println(hash)
    // Prints: v1_41011bfa1a996db6d0b1075981f5aa8f

    fmt.Println(structhash.Version(hash))
    // Prints: 1

    fmt.Printf("%x\n", structhash.Md5(s, 1))
    // Prints: 41011bfa1a996db6d0b1075981f5aa8f

    fmt.Printf("%x\n", structhash.Sha1(s, 1))
    // Prints: 5ff72df7212ce8c55838fb3ec6ad0c019881a772

    fmt.Printf("%x\n", md5.Sum(structhash.Dump(s, 1)))
    // Prints: 41011bfa1a996db6d0b1075981f5aa8f

    fmt.Printf("%x\n", sha1.Sum(structhash.Dump(s, 1)))
    // Prints: 5ff72df7212ce8c55838fb3ec6ad0c019881a772
}

Struct tags

structhash supports struct tags in the following forms:

  • hash:"-", or
  • hash:"name:{string} version:{number} lastversion:{number} method:{string}"

All fields are optional and may be ommitted. Their semantics is:

  • - - ignore field
  • name:{string} - rename field (may be useful when you want to rename field but keep hashes unchanged for backward compatibility)
  • version:{number} - ignore field if version passed to structhash is smaller than given number
  • lastversion:{number} - ignore field if version passed to structhash is greater than given number
  • method:{string} - use the return value of a field's method instead of the field itself

Example:

type MyStruct struct {
    Ignored    string `hash:"-"`
    Renamed    string `hash:"name:OldName version:1"`
    Legacy     string `hash:"version:1 lastversion:2"`
    Serialized error  `hash:"method:Error"`
}

Nil values

When hash is calculated, nil pointers, nil slices, and nil maps are treated equally to zero values of corresponding type. E.g., nil pointer to string is equivalent to empty string, and nil slice is equivalent to empty slice.

Documentation

Overview

Package structhash creates hash strings from arbitrary go data structures.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Dump

func Dump(c interface{}, version int) []byte

Dump takes a data structure and returns its byte representation. This can be useful if you need to use your own hashing function or formatter.

Example
type Person struct {
	Name   string
	Age    int
	Emails []string
	Extra  map[string]string
	Spouse *Person
}
bill := &Person{
	Name:   "Bill",
	Age:    24,
	Emails: []string{"bob@foo.org", "bob@bar.org"},
	Extra: map[string]string{
		"facebook": "Bob42",
	},
}
bob := &Person{
	Name:   "Bob",
	Age:    42,
	Emails: []string{"bob@foo.org", "bob@bar.org"},
	Extra: map[string]string{
		"facebook": "Bob42",
	},
	Spouse: bill,
}

fmt.Printf("md5:  %x\n", md5.Sum(Dump(bob, 1)))
fmt.Printf("sha1: %x\n", sha1.Sum(Dump(bob, 1)))
Output:

md5:  6a50d73f3bd0b9ebd001a0b610f387f0
sha1: c45f097a37366eaaf6ffbc7357c2272cd8fb64f6

func Hash

func Hash(c interface{}, version int) (string, error)

Hash takes a data structure and returns a hash string of that data structure at the version asked.

This function uses md5 hashing function and default formatter. See also Dump() function.

Example
type Person struct {
	Name   string
	Age    int
	Emails []string
	Extra  map[string]string
	Spouse *Person
}
bill := &Person{
	Name:   "Bill",
	Age:    24,
	Emails: []string{"bob@foo.org", "bob@bar.org"},
	Extra: map[string]string{
		"facebook": "Bob42",
	},
}
bob := &Person{
	Name:   "Bob",
	Age:    42,
	Emails: []string{"bob@foo.org", "bob@bar.org"},
	Extra: map[string]string{
		"facebook": "Bob42",
	},
	Spouse: bill,
}

hash, err := Hash(bob, 1)
if err != nil {
	panic(err)
}
fmt.Printf("%s", hash)
Output:

v1_6a50d73f3bd0b9ebd001a0b610f387f0
Example (Tags)
type Person struct {
	Ignored string            `hash:"-"`
	NewName string            `hash:"name:OldName version:1"`
	Age     int               `hash:"version:1"`
	Emails  []string          `hash:"version:1"`
	Extra   map[string]string `hash:"version:1 lastversion:2"`
	Spouse  *Person           `hash:"version:2"`
}
bill := &Person{
	NewName: "Bill",
	Age:     24,
	Emails:  []string{"bob@foo.org", "bob@bar.org"},
	Extra: map[string]string{
		"facebook": "Bob42",
	},
}
bob := &Person{
	NewName: "Bob",
	Age:     42,
	Emails:  []string{"bob@foo.org", "bob@bar.org"},
	Extra: map[string]string{
		"facebook": "Bob42",
	},
	Spouse: bill,
}
hashV1, err := Hash(bob, 1)
if err != nil {
	panic(err)
}
hashV2, err := Hash(bob, 2)
if err != nil {
	panic(err)
}
hashV3, err := Hash(bob, 3)
if err != nil {
	panic(err)
}
fmt.Printf("%s\n", hashV1)
fmt.Printf("%s\n", hashV2)
fmt.Printf("%s\n", hashV3)
Output:

v1_45d8a54c5f5fd287f197b26d128882cd
v2_babd7618f29036f5564816bee6c8a037
v3_012b06239f942549772c9139d66c121e

func Md5

func Md5(c interface{}, version int) []byte

Md5 takes a data structure and returns its md5 hash. This is a shorthand for md5.Sum(Dump(c, version)).

func Sha1

func Sha1(c interface{}, version int) []byte

Sha1 takes a data structure and returns its sha1 hash. This is a shorthand for sha1.Sum(Dump(c, version)).

func Version

func Version(h string) int

Version returns the version of the supplied hash as an integer or -1 on failure

Example
// A hash string gotten from Hash(). Returns the version as an int.
i := Version("v1_55743877f3ffd5fc834e97bc43a6e7bd")
fmt.Printf("%d", i)
Output:

1
Example (Errors)
// A hash string gotten from Hash(). Returns -1 on error.
i := Version("va_55743877f3ffd5fc834e97bc43a6e7bd")
fmt.Printf("%d", i)
Output:

-1

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL