Documentation
¶
Overview ¶
Example (FreelruMakeHasher) ¶
Example_freelruMakeHasher 展示 freelru 直接创建默认键哈希函数. 同一进程内同一个 hasher 对按 == 相等的键产生相同 uint32 哈希; NaN 不与自身相等, 不保证重复结果一致. 每次创建 hasher 都选择新 seed, 不同实例, 重启后或跨进程不保证相同, 不应持久化结果. freelru 保留其类型检查, 含接口的键类型需要自定义哈希; 普通缓存使用 NewDefault 等构造器即可自动选择 hasher.
package main
import (
"fmt"
"github.com/fufuok/freelru"
)
func main() {
hasher := freelru.MakeHasher[string]()
fmt.Println(hasher("lru key") == hasher("lru key"))
}
Output: true
Example (MaphashComparable) ¶
Example_maphashComparable 展示通用容器键直接使用标准库. seed 在容器构造时生成一次; 同一进程内相同 seed 对按 == 相等的键产生相同哈希, 不保证重启或跨进程一致. NaN 不与自身相等, 重复哈希也不保证相同; 接口中的 slice/map/func 等不可比较动态值会 panic.
package main
import (
"fmt"
"hash/maphash"
)
func main() {
seed := maphash.MakeSeed()
input := "map key"
h1 := maphash.Comparable(seed, input)
h2 := maphash.Comparable(seed, input)
fmt.Println(h1 == h2)
}
Output: true
Index ¶
- func AddBytes32(h uint32, b []byte) uint32
- func AddBytes64(h uint64, b []byte) uint64
- func AddString32(h uint32, s string) uint32
- func AddString64(h uint64, s string) uint64
- func AddUint32(h, u uint32) uint32
- func AddUint64(h uint64, u uint64) uint64
- func Hash(b []byte, h hash.Hash) []byte
- func HashBytes(b ...[]byte) string
- func HashBytes32(b ...[]byte) uint32
- func HashBytes64(b ...[]byte) uint64
- func HashSeedString(seed maphash.Seed, s string) uint64
- func HashSeedUint64(seed maphash.Seed, n uint64) uint64
- func HashString(s ...string) string
- func HashString32(s ...string) uint32
- func HashString64(s ...string) uint64
- func HashUint32(u uint32) uint32
- func HashUint64(u uint64) uint64
- func Hmac(b []byte, key []byte, h func() hash.Hash) []byte
- func HmacSHA1(b, key []byte) []byte
- func HmacSHA1Hex(s, key string) string
- func HmacSHA256(b, key []byte) []byte
- func HmacSHA256Hex(s, key string) string
- func HmacSHA512(b, key []byte) []byte
- func HmacSHA512Hex(s, key string) string
- func MD5(b []byte) []byte
- func MD5BytesHex(bs []byte) string
- func MD5Hex(s string) string
- func MD5Reader(r io.Reader) (string, error)
- func MD5Sum(filename string) (string, error)
- func MemHash(s string) uint64
- func MemHash32(s string) uint32
- func MemHashb(b []byte) uint64
- func MemHashb32(b []byte) uint32
- func MustMD5Sum(filename string) string
- func Sha1(b []byte) []byte
- func Sha1Hex(s string) string
- func Sha256(b []byte) []byte
- func Sha256Hex(s string) string
- func Sha512(b []byte) []byte
- func Sha512Hex(s string) string
- func Sum32(s string) uint32
- func Sum64(s string) uint64
- func SumBytes32(bs []byte) uint32
- func SumBytes64(bs []byte) uint64
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddBytes32 ¶
AddBytes32 用 b 延续稳定的 FNV-1a 32 位哈希. 相同 h 和 b 在重启后和跨进程仍相同.
func AddBytes64 ¶
AddBytes64 用 b 延续稳定的 FNV-1a 64 位哈希. 字节语义与 AddString64 相同, 相同 h 和 b 在重启后和跨进程仍相同, 可用于持久化增量哈希.
func AddString32 ¶
AddString32 用 s 延续稳定的 FNV-1a 32 位哈希. 从相同初始 h 开始时, 相同 s 在重启后和跨进程仍相同.
func AddString64 ¶
AddString64 用 s 延续稳定的 FNV-1a 64 位哈希. 从相同初始 h 开始时, 相同 s 在重启后和跨进程结果仍相同.
func AddUint32 ¶
AddUint32 用 u 的 4 字节大端表示延续稳定的 FNV-1a 哈希. 相同 h 和 u 在重启后和跨进程仍相同; 历史注释中的 8 字节描述不正确, 实际只处理 4 字节.
func Hash ¶
Hash 重置 h, 写入 b 并返回摘要; h 为 nil 时使用 MD5. 输出稳定性由 h 的算法及参数决定; MD5/SHA 等确定性算法对相同输入在重启后和跨进程仍相同. 带随机种子的实现不保证跨实例或跨进程相同; 本函数会修改 h, 不应并发共用同一实例.
Example ¶
ExampleHash 展示显式选择摘要算法以及兼容的 nil 默认值. Hash 会重置传入的 hash.Hash, 因此不能用来延续该实例已有的摘要状态, 也不要并发共享该实例. 使用 SHA-256 等确定性算法时, 相同内容在同一进程, 重启后和跨进程的结果相同. 对任意自定义 hash.Hash, 稳定性由该实例的算法和种子决定; 例如 maphash.Hash 不保证跨进程一致. Hash(b, nil) 使用 MD5, 与 MD5(b) 等价; 新调用方宜显式选算法或使用对应的 Sha256 等助手.
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"github.com/fufuok/pkg/xhash"
)
func main() {
input := []byte("12345")
sum := xhash.Hash(input, sha256.New())
fmt.Println(hex.EncodeToString(sum) == xhash.Sha256Hex(string(input)))
fmt.Println(hex.EncodeToString(xhash.Hash(input, nil)) == xhash.MD5BytesHex(input))
}
Output: true true
func HashBytes ¶
HashBytes 拼接字节并返回 HashBytes64 的稳定十进制形式. 相同字节在重启后和跨进程仍得到相同字符串; 十进制形式用于展示或旧键, 数值调用方应使用 HashBytes64.
func HashBytes32 ¶
HashBytes32 拼接字节并返回稳定的 FNV-1a 32 位哈希. 相同拼接内容在重启后和跨进程仍得到相同结果; 仅当拼接字节表示相同字符串内容时, 才与 HashString32 一致.
func HashBytes64 ¶
HashBytes64 拼接字节并返回稳定的 FNV-1a 64 位哈希. 相同拼接内容在重启后和跨进程仍得到相同结果. 拼接不保留各参数边界, 相同字节内容与 HashString64 一致.
func HashSeedString ¶
HashSeedString 直接返回 maphash.String(seed, s). 相同 seed 和输入在当前进程内结果相同; seed 必须由 maphash.MakeSeed 创建, 零值会 panic. seed 不能跨进程重建, 结果不可作为重启后或跨进程稳定的协议值.
Example ¶
ExampleHashSeedString 展示固定保存一个 maphash.Seed 的进程内用法. HashSeedString 等价于 maphash.String; seed 必须由 maphash.MakeSeed 创建并复用, 零 seed 会 panic. HashSeedUint64 是读取 seed 内部表示的旧整数混合算法, 不等于哈希整数文本或 maphash.Comparable. 两者对各自相同 seed 和输入在同一进程内结果相同, 但不保证重启后或跨进程相同, 不能用于稳定分桶. HashSeedUint64 仅用于兼容现有进程内调用, 新容器的整数键直接使用 maphash.Comparable.
package main
import (
"fmt"
"hash/maphash"
"github.com/fufuok/pkg/xhash"
)
func main() {
seed := maphash.MakeSeed()
input := "cache key"
h1 := xhash.HashSeedString(seed, input)
h2 := xhash.HashSeedString(seed, input)
n1 := xhash.HashSeedUint64(seed, 42)
n2 := xhash.HashSeedUint64(seed, 42)
fmt.Println(h1 == h2)
fmt.Println(n1 == n2)
}
Output: true true
func HashSeedUint64 ¶
HashSeedUint64 用进程内 maphash 种子混合 n. 相同 seed 和 n 在当前进程内结果相同, 但重启或其他进程可能不同; 算法也不同于 HashUint64. 该兼容实现读取 maphash.Seed 的内部表示, 不应作为新的稳定哈希接口.
func HashString ¶
HashString 拼接字符串并返回 HashString64 的稳定十进制形式. 相同参数在重启后和跨进程仍得到相同字符串; 现有代理 token 依赖此精确格式, 它不是密码学签名. 参数间不添加分隔符; 需要数值时直接使用 HashString64, 需要区分参数边界时应先明确编码.
Example ¶
ExampleHashString 展示协议使用的十进制字符串包装. HashString 和 HashBytes 对相同拼接内容在同一进程, 重启后和跨进程都得到相同字符串. 它们分别格式化 HashString64 和 HashBytes64 的结果, 数值计算可直接使用后两者. 拼接不加分隔符, 因而 ("12", "345") 与 ("12345") 相同; 需要区分字段边界时应先明确编码.
package main
import (
"fmt"
"github.com/fufuok/pkg/xhash"
)
func main() {
const input = "12345"
fmt.Println(xhash.HashString(input))
fmt.Println(xhash.HashBytes([]byte(input)))
}
Output: 16534377278781491704 16534377278781491704
func HashString32 ¶
HashString32 拼接字符串并返回稳定的 FNV-1a 32 位哈希. 相同参数拼接后的结果在重启后和跨进程仍相同, 但值域远小于 HashString64. 使用独立的 32 位 FNV 参数, 不是 HashString64 结果的低 32 位.
func HashString64 ¶
HashString64 拼接字符串并返回稳定的 FNV-1a 64 位哈希. 相同参数拼接后的结果在重启后和跨进程仍相同, 部署灰度阈值依赖此值. 拼接不添加分隔符, 因此不区分 ("ab", "c") 与 ("a", "bc") 的参数边界.
func HashUint32 ¶
HashUint32 返回 u 的 4 字节大端表示的稳定 FNV-1a 哈希. 相同 u 在重启后和跨进程仍得到相同结果, 不是 runtime memhash.
func HashUint64 ¶
HashUint64 返回 u 的 8 字节大端表示的稳定 FNV-1a 哈希. 相同 u 在重启后和跨进程仍得到相同结果, 不使用进程内 maphash 种子.
func Hmac ¶
Hmac 使用 h 构造带密钥的 MAC, h 为 nil 时使用 MD5. h 应每次返回新的确定性密码学哈希实例; 算法及参数一致时, 相同输入和密钥在重启后及跨进程仍相同. nil 回退是兼容行为, 新调用方应显式传入 sha256.New 等哈希工厂.
func HmacSHA1Hex ¶
HmacSHA1Hex 返回稳定的 HMAC-SHA-1 小写十六进制值. 相同消息和密钥在重启后和跨进程仍相同. 可用于兼容既有校验器, 新代码应使用 HMAC-SHA-256. 对相同消息和密钥, 它是 HmacSHA1 原始结果的小写十六进制表示.
func HmacSHA256 ¶
HmacSHA256 返回稳定的 HMAC-SHA-256 原始值. 相同消息和密钥在重启后和跨进程仍相同, key 应按密钥保护.
func HmacSHA256Hex ¶
HmacSHA256Hex 返回稳定的 HMAC-SHA-256 小写十六进制值. 相同消息和密钥在重启后和跨进程仍相同, 不能当作无密钥校验和. 与相同内容的 HmacSHA256 原始结果经十六进制编码后相同, 验证原始 MAC 时应使用 hmac.Equal.
Example ¶
ExampleHmacSHA256Hex 展示带密钥的认证码. HmacSHA256 返回原始字节, HmacSHA256Hex 返回对应的小写十六进制文本. HmacSHA512/HmacSHA512Hex 和 HmacSHA1/HmacSHA1Hex 的原始与文本关系相同, 但算法及输出不同. 这些固定算法对相同消息和密钥在同一进程, 重启后和跨进程都得到相同 MAC, 新协议优先使用 HMAC-SHA-256. Hmac 允许显式传 sha256.New 等密码学哈希工厂, 传 nil 时兼容地使用 MD5; 必须与校验方约定相同算法. HmacSHA1/HmacSHA1Hex 仅用于兼容既有协议; 验证原始 MAC 时应使用 hmac.Equal, 不直接比较文本.
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"github.com/fufuok/pkg/xhash"
)
func main() {
const input = "Fufu 中 文加密/解密~{a"
fmt.Println(xhash.HmacSHA256Hex(input, "Fufu"))
fmt.Println(hex.EncodeToString(xhash.HmacSHA256([]byte(input), []byte("Fufu"))) == xhash.HmacSHA256Hex(input, "Fufu"))
fmt.Println(hex.EncodeToString(xhash.Hmac([]byte(input), []byte("Fufu"), sha256.New)) == xhash.HmacSHA256Hex(input, "Fufu"))
}
Output: 6d502095be042aab03ac7ae36dd0ca504e54eb72569547dca4e16e5de605ae7c true true
func HmacSHA512 ¶
HmacSHA512 返回稳定的 HMAC-SHA-512 原始值. 相同消息和密钥在重启后和跨进程仍相同. 适用于带密钥的完整性校验, 不适合进程内高频 Map.
func HmacSHA512Hex ¶
HmacSHA512Hex 返回稳定的 HMAC-SHA-512 小写十六进制值. 相同消息和密钥在重启后和跨进程仍相同. 需要原始字节时使用 HmacSHA512, 不能与 HmacSHA256Hex 的输出直接互换.
func MD5BytesHex ¶
MD5BytesHex 返回稳定的 MD5 小写十六进制摘要. 相同字节在重启后和跨进程仍得到相同字符串. nil 和空输入都按空内容处理, 可持久化, 但不应新增安全用途. 需要原始 16 字节时使用 MD5; 相同内容的字符串可使用 MD5Hex, 输出格式一致.
func MD5Hex ¶
MD5Hex 返回稳定的 MD5 小写十六进制摘要. 相同输入在重启后和跨进程仍得到相同字符串. 现有 token, 签名和 AES 密钥派生依赖此输出; MD5 不抗碰撞, 不应新增安全用途.
Example ¶
ExampleMD5Hex 展示协议使用的 MD5 十六进制输出. MD5Hex 与 MD5BytesHex 对相同内容在同一进程, 重启后和跨进程都相同. MD5 返回原始 16 字节, 经 hex.EncodeToString 后与这两个字符串助手一致. nil 字节切片和空输入都按空内容处理; MD5 仅用于兼容或非安全校验, 不适合新增安全设计.
package main
import (
"encoding/hex"
"fmt"
"github.com/fufuok/pkg/xhash"
)
func main() {
const input = "12345"
fmt.Println(xhash.MD5Hex(input))
fmt.Println(xhash.MD5BytesHex([]byte(input)))
fmt.Println(hex.EncodeToString(xhash.MD5([]byte(input))) == xhash.MD5Hex(input))
}
Output: 827ccb0eea8a706c4c34a16891f84e7b 827ccb0eea8a706c4c34a16891f84e7b true
func MD5Reader ¶
MD5Reader 返回从 r 读取的全部字节的稳定 MD5. 相同输入字节在重启后和跨进程仍相同. 非 EOF 读取错误原样返回, 且不返回部分摘要.
Example ¶
ExampleMD5Reader 展示流和文件摘要函数族. MD5Reader 从当前位置读到 EOF, 不负责关闭 r; 相同已读字节在同一进程, 重启后和跨进程的摘要相同. 文件路径可用 MD5Sum(filename), 它负责打开和关闭文件, 读取成功时等价于同内容的 MD5Reader. MD5Sum 遇到目录返回 ("", nil), 打开或读取失败返回错误; 不能只通过 err 判断结果是有效摘要. MustMD5Sum(filename) 忽略 MD5Sum 的错误并返回空字符串, 仅适合允许缺失摘要的场景.
package main
import (
"fmt"
"strings"
"github.com/fufuok/pkg/xhash"
)
func main() {
sum, err := xhash.MD5Reader(strings.NewReader("12345"))
if err != nil {
fmt.Println("read failed:", err)
return
}
fmt.Println(sum)
}
Output: 827ccb0eea8a706c4c34a16891f84e7b
func MemHash ¶
MemHash 返回进程内 runtime memhash. 同一进程内相同输入得到相同值, 但重启或其他进程可能不同; 不可持久化, 跨进程传输或用于稳定分片. 空字符串按空内容处理; memhash 在长度为零时不会解引用数据指针.
func MemHash32 ¶
MemHash32 使用 offset32 初始化 runtime memhash 并截断为 32 位, 不保证等于截断 MemHash 的结果. 同一进程内相同输入得到相同值, 但重启或其他进程可能不同; 只能在单个进程内使用, 稳定替代是 Sum32.
func MemHashb ¶
MemHashb 返回进程内 runtime memhash. 同一进程内相同输入得到相同值, 但重启或其他进程可能不同; 仅适合进程内缓存键. nil 和空切片按空内容处理, 使用公开 unsafe API 直接传递数据指针, 保留原 seed 和算法.
Example ¶
ExampleMemHashb 展示当前进程内缓存键的用法. MemHash 与 MemHashb 分别接收字符串和字节, 同一进程内对相同内容的结果相同; MemHash32 与 MemHashb32 同理. 32 位接口使用不同的初始 seed, 不是截断 MemHash/MemHashb 的 64 位结果; 只能在选择相应宽度时替换. 这些结果不保证重启后或跨进程一致, 不能用作持久化键或稳定分桶; 新代码优先使用固定 seed 的 maphash.
package main
import (
"fmt"
"github.com/fufuok/pkg/xhash"
)
func main() {
input := []byte("request body")
h1 := xhash.MemHashb(input)
h2 := xhash.MemHashb(input)
fmt.Println(h1 == h2)
fmt.Println(h1 == xhash.MemHash(string(input)))
fmt.Println(xhash.MemHashb32(input) == xhash.MemHash32(string(input)))
}
Output: true true true
func MemHashb32 ¶
MemHashb32 使用 offset32 初始化 runtime memhash 并截断为 32 位, 不保证等于截断 MemHashb 的结果. 同一进程内相同输入得到相同值, 但重启或其他进程可能不同, 也不能与 SumBytes32 互换.
func MustMD5Sum ¶
MustMD5Sum 返回稳定的文件 MD5, 任意错误都返回空字符串. 文件内容相同则重启后和跨进程仍相同. 缺失文件和目录因此无法区分, 需要识别失败时应使用 MD5Sum.
func Sha256Hex ¶
Sha256Hex 返回稳定的 SHA-256 小写十六进制摘要. 相同输入在重启后和跨进程仍相同. 适用于内容校验和持久化标识, 不是带密钥的 MAC, 也不适合高频缓存.
Example ¶
ExampleSha256Hex 展示内容校验摘要. Sha256 接受字节并返回原始摘要, Sha256Hex 接受字符串并返回对应的小写十六进制文本. Sha512/Sha512Hex 和 Sha1/Sha1Hex 的原始与文本关系相同, 但算法和摘要长度不同, 不能直接互换结果. 每个算法对相同内容在同一进程, 重启后和跨进程都返回相同摘要; 无密钥摘要不是 MAC. Sha1/Sha1Hex 只用于兼容既有协议, 新的内容校验优先使用 Sha256/Sha256Hex.
package main
import (
"encoding/hex"
"fmt"
"github.com/fufuok/pkg/xhash"
)
func main() {
const input = "Fufu 中 文加密/解密~{a"
fmt.Println(xhash.Sha256Hex(input))
fmt.Println(hex.EncodeToString(xhash.Sha256([]byte(input))) == xhash.Sha256Hex(input))
}
Output: ed3772cefd8991edac6d198df7b62c224b92038e2d435a9a1e2734211e5b5e0b true
func Sum64 ¶
Sum64 返回稳定的 FNV-1a 64 位哈希. 相同输入在当前进程, 重启后和其他进程中都得到相同结果, 是 HashString64 的冻结基础算法.
Example ¶
ExampleSum64 展示稳定分桶函数族的相同输入结果. 这些函数不依赖进程随机种子, 相同输入在当前进程, 重启后和其他进程中都相同. Sum64/Sum32 处理字符串, SumBytes64/SumBytes32 对相同字节内容产生对应的相同值. HashString64/HashString32 和 HashBytes64/HashBytes32 先直接拼接参数, 不保留参数边界. AddString64/AddString32 与 AddBytes64/AddBytes32 从给定 h 继续计算, 可替代先拼接再 Sum. HashUint64/HashUint32 与 AddUint64/AddUint32 按固定宽度的大端字节处理整数, 不等于哈希十进制文本. 32 位和 64 位版本使用各自的 FNV 参数, 不能用截断 64 位结果替代 32 位版本.
package main
import (
"fmt"
"github.com/fufuok/pkg/xhash"
)
func main() {
const input = "12345"
const (
stableOffset64 uint64 = 14695981039346656037
stableOffset32 uint32 = 2166136261
)
fmt.Println(xhash.Sum64(input))
fmt.Println(xhash.SumBytes64([]byte(input)))
fmt.Println(xhash.Sum32(input))
fmt.Println(xhash.SumBytes32([]byte(input)))
fmt.Println(xhash.HashString64(input))
fmt.Println(xhash.HashString32(input))
fmt.Println(xhash.HashBytes64([]byte(input)))
fmt.Println(xhash.HashBytes32([]byte(input)))
fmt.Println(xhash.Sum64(input) == xhash.AddString64(stableOffset64, input))
fmt.Println(xhash.SumBytes64([]byte(input)) == xhash.AddBytes64(stableOffset64, []byte(input)))
fmt.Println(xhash.Sum32(input) == xhash.AddString32(stableOffset32, input))
fmt.Println(xhash.SumBytes32([]byte(input)) == xhash.AddBytes32(stableOffset32, []byte(input)))
fmt.Println(xhash.HashUint64(1) == xhash.AddUint64(stableOffset64, 1))
fmt.Println(xhash.HashUint32(1) == xhash.AddUint32(stableOffset32, 1))
// 固定桶数和编码规则时, 同一键在各进程中落入相同的桶.
fmt.Println("bucket:", xhash.Sum64(input)%100)
// 分段计算可以避免为临时拼接分配字符串, 结果与一次性输入相同.
fmt.Println(xhash.AddString64(xhash.Sum64("12"), "345") == xhash.Sum64(input))
}
Output: 16534377278781491704 16534377278781491704 1136836824 1136836824 16534377278781491704 1136836824 16534377278781491704 1136836824 true true true true true true bucket: 4 true
func SumBytes32 ¶
SumBytes32 返回稳定的 FNV-1a 32 位哈希. 相同字节内容与 Sum32 一致, 重启后和跨进程仍相同, 不能替换为 maphash.
func SumBytes64 ¶
SumBytes64 返回稳定的 FNV-1a 64 位哈希. 相同字节内容与 Sum64 一致, 重启后和跨进程仍相同, 可用于持久化分桶.
Types ¶
This section is empty.