Documentation
¶
Overview ¶
Package hashy provides deterministic, structural hashing of arbitrary Go values, including structs, slices, maps, and primitive types.
The package is built around a configurable hasher that traverses a value using reflection, feeds each field and element into a 64-bit FNV-1a hash function, and returns a reproducible uint64 digest. The same logical value always produces the same hash within a single binary; the hash is not stable across different Go versions or architectures.
Basic Usage ¶
h, err := hashy.Hash(myStruct)
fmt.Printf("%016x\n", h)
// Multiple values are hashed as a tuple:
h, err = hashy.Hash(userID, role, timestamp)
Output Formats ¶
Hash returns a raw uint64. Convenience wrappers encode the result in common formats:
Hash256(v) → SHA-256 of the uint64, as a hex string Hash16Padded(v) → zero-padded 16-character hex string Hash16(v) → hexadecimal string Hash10(v) → decimal string Hash32(v) → base-32 string Hash64(v)→ base-64 string
Configuration ¶
Hash behaviour can be tuned by passing an *Options value (built via NewOptions().WithTagName(...).WithZeroNil(true).Build()) as the final variadic argument:
opts := hashy.NewOptions().WithSlicesAsSets(true).Build() h, err := hashy.Hash(mySlice, opts)
Notable options include ZeroNil (treat nil pointers as zero values), IgnoreZeroValue (omit zero-value fields from the hash), SlicesAsSets (order-independent slice hashing), and UseStringer (use fmt.Stringer when available). The TagName option controls which struct tag is inspected for per-field directives such as "ignore" or "set".
Structs may implement the Hashable, FieldSelector, or MapSelector interfaces to customise how they are hashed.
hashy is safe for concurrent use when options are nil or were built with WithHasherFunc. Sharing options built with WithHasher across goroutines causes a data race because a single hash.Hash64 instance is not goroutine-safe.
Index ¶
- func DefaultOptions() *hashOptions
- func Hash(data ...any) (uint64, error)
- func Hash10(data ...any) (string, error)
- func Hash16(data ...any) (string, error)
- func Hash16Padded(data ...any) (string, error)
- func Hash32(data ...any) (string, error)
- func Hash64(data ...any) (string, error)
- func Hash256(data ...any) (string, error)
- func HashHex16(data ...any) (string, error)
- func HashValue(value any, options *hashOptions) (uint64, error)
- func NewHash(algo HashAlgorithm) hash.Hash
- func NewHash64(algo HashAlgorithm) hash.Hash64
- type ErrNotStringer
- type FieldSelector
- type HashAlgorithm
- type Hashable
- type MapSelector
- type OptionsBuilder
- func (b *OptionsBuilder) Build() *hashOptions
- func (b *OptionsBuilder) WithHasher(h hash.Hash64) *OptionsBuilderdeprecated
- func (b *OptionsBuilder) WithHasherFunc(fn func() hash.Hash64) *OptionsBuilder
- func (b *OptionsBuilder) WithIgnoreZeroValue(ignore bool) *OptionsBuilder
- func (b *OptionsBuilder) WithSlicesAsSets(asSets bool) *OptionsBuilder
- func (b *OptionsBuilder) WithTagName(name string) *OptionsBuilder
- func (b *OptionsBuilder) WithUseStringer(useStringer bool) *OptionsBuilder
- func (b *OptionsBuilder) WithZeroNil(zeroNil bool) *OptionsBuilder
- type SelectField
- type SelectMapEntry
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultOptions ¶
func DefaultOptions() *hashOptions
DefaultOptions returns default options for hashing.
Returns:
- A pointer to a newly created `Options` instance with the default values.
func Hash ¶
Hash generates a 64-bit hash value for the given data. It accepts variadic arguments - if only one argument is provided, it hashes that value. If multiple arguments are provided, it hashes them as a tuple. The last argument can optionally be *Options.
Examples:
hash, err := Hash(myStruct) // Single value hash, err := Hash(val1, val2, val3) // Multiple values hash, err := Hash(myStruct, opts) // With options hash, err := Hash(val1, val2, val3, opts) // Multiple values with options
The hash is deterministic: identical values always produce identical hashes.
Returns:
- uint64: The computed hash value (never zero for valid inputs)
- error: Non-nil if hashing fails
func Hash10 ¶
Hash10 generates a decimal hash string for the given data. It accepts variadic arguments - if only one argument is provided, it hashes that value. If multiple arguments are provided, it hashes them as a tuple. The last argument can optionally be *Options.
Returns:
- string: The computed hash string (never empty for valid inputs)
- error: Non-nil if hashing fails
Example:
hash, err := Hash10(myStruct) // Single value hash, err := Hash10(val1, val2, val3) // Multiple values hash, err := Hash10(myStruct, opts) // With options hash, err := Hash10(val1, val2, val3, opts) // Multiple values with options
The hash is deterministic: identical values always produce identical hashes.
func Hash16 ¶
Hash16 generates a hexadecimal hash string for the given data. It accepts variadic arguments - if only one argument is provided, it hashes that value. If multiple arguments are provided, it hashes them as a tuple. The last argument can optionally be *Options.
Returns:
- string: The computed hash string (never empty for valid inputs)
- error: Non-nil if hashing fails
Example:
hash, err := Hash16(myStruct) // Single value hash, err := Hash16(val1, val2, val3) // Multiple values hash, err := Hash16(myStruct, opts) // With options hash, err := Hash16(val1, val2, val3, opts) // Multiple values with options
The hash is deterministic: identical values always produce identical hashes.
func Hash16Padded ¶
Hash16Padded generates a hexadecimal hash string for the given data. It accepts variadic arguments - if only one argument is provided, it hashes that value. If multiple arguments are provided, it hashes them as a tuple. The last argument can optionally be *Options.
Returns:
- string: The computed hash string (never empty for valid inputs)
- error: Non-nil if hashing fails
Example:
hash, err := Hash16Padded(myStruct) // Single value hash, err := Hash16Padded(val1, val2, val3) // Multiple values hash, err := Hash16Padded(myStruct, opts) // With options hash, err := Hash16Padded(val1, val2, val3, opts) // Multiple values with options
The hash is deterministic: identical values always produce identical hashes.
func Hash32 ¶
Hash32 generates a base32 encoded hash string for the given data. It accepts variadic arguments - if only one argument is provided, it hashes that value. If multiple arguments are provided, it hashes them as a tuple. The last argument can optionally be *Options.
Returns:
- string: The computed hash string (never empty for valid inputs)
- error: Non-nil if hashing fails
Example:
hash, err := Hash32(myStruct) // Single value hash, err := Hash32(val1, val2, val3) // Multiple values hash, err := Hash32(myStruct, opts) // With options hash, err := Hash32(val1, val2, val3, opts) // Multiple values with options
The hash is deterministic: identical values always produce identical hashes.§
func Hash64 ¶
Hash64 generates a base64 encoded hash string for the given data. It accepts variadic arguments - if only one argument is provided, it hashes that value. If multiple arguments are provided, it hashes them as a tuple. The last argument can optionally be *Options.
Returns:
- string: The computed hash string (never empty for valid inputs)
- error: Non-nil if hashing fails
Example:
hash, err := Hash64(myStruct) // Single value hash, err := Hash64(val1, val2, val3) // Multiple values hash, err := Hash64(myStruct, opts) // With options hash, err := Hash64(val1, val2, val3, opts) // Multiple values with options
The hash is deterministic: identical values always produce identical hashes.
func Hash256 ¶
Hash256 generates a 256-bit hash string for the given data. It accepts variadic arguments - if only one argument is provided, it hashes that value. If multiple arguments are provided, it hashes them as a tuple. The last argument can optionally be *Options.
Returns:
- string: The computed hash string (never empty for valid inputs)
- error: Non-nil if hashing fails
Example:
hash, err := Hash256(myStruct) // Single value hash, err := Hash256(val1, val2, val3) // Multiple values hash, err := Hash256(myStruct, opts) // With options hash, err := Hash256(val1, val2, val3, opts) // Multiple values with options
The hash is deterministic: identical values always produce identical hashes.
func HashHex16 ¶
HashHex16 generates a hexadecimal hash string for the given data. It accepts variadic arguments - if only one argument is provided, it hashes that value. If multiple arguments are provided, it hashes them as a tuple. The last argument can optionally be *Options.
Returns:
- string: The computed hash string (never empty for valid inputs)
- error: Non-nil if hashing fails
Example:
hash, err := HashHex16(myStruct) // Single value hash, err := HashHex16(val1, val2, val3) // Multiple values hash, err := HashHex16(myStruct, opts) // With options hash, err := HashHex16(val1, val2, val3, opts) // Multiple values with options
The hash is deterministic: identical values always produce identical hashes.
func HashValue ¶
HashValue generates a 64-bit hash value for a single value with options. This is the primary hashing function.
Parameters:
- value: Any Go value (struct, slice, map, primitive, etc.)
- options: Optional configuration (nil uses defaults)
Returns:
- uint64: The computed hash value (never zero for valid inputs)
- error: Non-nil if hashing fails
Concurrency: HashValue is safe for concurrent use provided that either (a) options is nil, or (b) the options were built with WithHasherFunc so that a fresh hash.Hash64 is created for every call. Reusing options that carry a single hash.Hash64 instance (via WithHasher) from multiple goroutines simultaneously causes a data race.
Example:
value := 1 hash, err := HashValue(value, nil) fmt.Println(hash, err) // 1 nil
func NewHash ¶
func NewHash(algo HashAlgorithm) hash.Hash
NewHash creates a new hash.Hash instance for the given algorithm.
Parameters:
- algo: The hash algorithm to use.
Returns:
- hash.Hash: The hash.Hash instance.
func NewHash64 ¶
func NewHash64(algo HashAlgorithm) hash.Hash64
NewHash64 creates a new hash.Hash64 instance for the given algorithm. Algorithms that do not natively implement hash.Hash64 (e.g. MD5, SHA-*) fall back to FNV-1a rather than panicking.
Parameters:
- algo: The hash algorithm to use.
Returns:
- hash.Hash64: The hash.Hash64 instance.
Types ¶
type ErrNotStringer ¶
type ErrNotStringer struct {
Field string
}
ErrNotStringer is returned when there's an error with hash:"string"
Parameters:
- Field: The name of the field that caused the error.
Returns:
- A pointer to the `ErrNotStringer` struct.
func (*ErrNotStringer) Error ¶
func (e *ErrNotStringer) Error() string
Error returns the error message for the `ErrNotStringer` type.
Returns:
- A string representing the error message.
Example:
err := &ErrNotStringer{Field: "name"}
fmt.Println(err.Error()) // "pkg.hash: field \"name\" has hash:\"string\" tag but does not implement fmt.Stringer"
type FieldSelector ¶
type FieldSelector interface {
SelectField() SelectField
}
FieldSelector is an interface that can optionally be implemented by a struct. It will be called for each field in the struct to check whether it should be included in the hash.
type HashAlgorithm ¶
type HashAlgorithm string
HashAlgorithm represents a hash algorithm.
const ( // H_CRC32 is a CRC32 hash algorithm. H_CRC32 HashAlgorithm = "crc32" // H_CRC64 is a CRC64 hash algorithm. H_CRC64 HashAlgorithm = "crc64" // H_MD5 is a MD5 hash algorithm. H_MD5 HashAlgorithm = "md5" // H_SHA1 is a SHA1 hash algorithm. H_SHA1 HashAlgorithm = "sha1" // H_SHA224 is a SHA224 hash algorithm. H_SHA224 HashAlgorithm = "sha224" // H_SHA256 is a SHA256 hash algorithm. H_SHA256 HashAlgorithm = "sha256" // H_SHA384 is a SHA384 hash algorithm. H_SHA384 HashAlgorithm = "sha384" // H_SHA512 is a SHA512 hash algorithm. H_SHA512 HashAlgorithm = "sha512" // H_SHA512_224 is a SHA512_224 hash algorithm. H_SHA512_224 HashAlgorithm = "sha512_224" // H_SHA512_256 is a SHA512_256 hash algorithm. H_SHA512_256 HashAlgorithm = "sha512_256" )
type Hashable ¶
Hashable is an interface that can optionally be implemented by a struct. It will be called to get the hash of the struct. It returns a string representing the hash of the struct. If the function returns an error, the hash will not be included in the hash.
type MapSelector ¶
type MapSelector interface {
SelectMapEntry() SelectMapEntry
}
MapSelector is an interface that can optionally be implemented by a struct. It will be called for each map field in the struct to check whether it should be included in the hash.
type OptionsBuilder ¶
type OptionsBuilder struct {
// contains filtered or unexported fields
}
OptionsBuilder provides a fluent interface for building Options. It allows for chaining of method calls to configure the Options struct.
func NewOptions ¶
func NewOptions() *OptionsBuilder
NewOptions creates a new options builder with defaults.
Returns:
- A pointer to a newly created `OptionsBuilder` instance with the default values.
func (*OptionsBuilder) Build ¶
func (b *OptionsBuilder) Build() *hashOptions
Build builds the options.
Returns:
- A pointer to the `Options` struct.
Example:
builder := NewOptions().Build() opts := builder.Build()
func (*OptionsBuilder) WithHasher
deprecated
func (b *OptionsBuilder) WithHasher(h hash.Hash64) *OptionsBuilder
WithHasher sets the hash function to use.
Parameters:
- h: The hash function to use.
Returns:
- A pointer to the `OptionsBuilder` struct.
Deprecated: prefer WithHasherFunc for concurrent-safe use. A single hash.Hash64 instance is stateful; passing the same *hashOptions to Hash/HashValue from multiple goroutines concurrently causes a data race.
Example:
builder := NewOptions().WithHasher(fnv.New64a()) opts := builder.Build()
func (*OptionsBuilder) WithHasherFunc ¶
func (b *OptionsBuilder) WithHasherFunc(fn func() hash.Hash64) *OptionsBuilder
WithHasherFunc sets a factory function that creates a fresh hash.Hash64 for every hashing operation. Using a factory function is safe for concurrent use by multiple goroutines.
Parameters:
- fn: A function that returns a new hash.Hash64 instance each time it is called.
Returns:
- A pointer to the `OptionsBuilder` struct.
Example:
builder := NewOptions().WithHasherFunc(fnv.New64a) opts := builder.Build()
func (*OptionsBuilder) WithIgnoreZeroValue ¶
func (b *OptionsBuilder) WithIgnoreZeroValue(ignore bool) *OptionsBuilder
WithIgnoreZeroValue sets whether zero value fields should be ignored for hash calculation.
Parameters:
- ignore: A boolean indicating whether zero value fields should be ignored for hash calculation.
Returns:
- A pointer to the `OptionsBuilder` struct.
Example:
builder := NewOptions().WithIgnoreZeroValue(true) opts := builder.Build()
func (*OptionsBuilder) WithSlicesAsSets ¶
func (b *OptionsBuilder) WithSlicesAsSets(asSets bool) *OptionsBuilder
WithSlicesAsSets sets whether slices should be treated as sets.
Parameters:
- asSets: A boolean indicating whether slices should be treated as sets.
Returns:
- A pointer to the `OptionsBuilder` struct.
Example:
builder := NewOptions().WithSlicesAsSets(true) opts := builder.Build()
func (*OptionsBuilder) WithTagName ¶
func (b *OptionsBuilder) WithTagName(name string) *OptionsBuilder
WithTagName sets the struct tag to look at when hashing the structure.
Parameters:
- name: The name of the struct tag to look at.
Returns:
- A pointer to the `OptionsBuilder` struct.
Example:
builder := NewOptions().WithTagName("json")
opts := builder.Build()
func (*OptionsBuilder) WithUseStringer ¶
func (b *OptionsBuilder) WithUseStringer(useStringer bool) *OptionsBuilder
WithUseStringer sets whether fmt.Stringer should be used always.
Parameters:
- useStringer: A boolean indicating whether fmt.Stringer should be used always.
Returns:
- A pointer to the `OptionsBuilder` struct.
Example:
builder := NewOptions().WithUseStringer(true) opts := builder.Build()
func (*OptionsBuilder) WithZeroNil ¶
func (b *OptionsBuilder) WithZeroNil(zeroNil bool) *OptionsBuilder
WithZeroNil sets whether nil pointer should be treated equal to a zero value of pointed type.
Parameters:
- zeroNil: A boolean indicating whether nil pointer should be treated equal to a zero value of pointed type.
Returns:
- A pointer to the `OptionsBuilder` struct.
Example:
builder := NewOptions().WithZeroNil(true) opts := builder.Build()
type SelectField ¶
SelectField is a function that can be used to check if a field should be included in the hash. It returns a boolean indicating whether the field should be included in the hash. If the function returns an error, the field will not be included in the hash.
type SelectMapEntry ¶
SelectMapEntry is a function that can be used to check if a map field should be included in the hash. It returns a boolean indicating whether the map field should be included in the hash. If the function returns an error, the map field will not be included in the hash.