You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Go泛型实现类C++ std::hash的哈希函数及性能对比

问题:用Go泛型实现类似C++ std::hash的哈希函数

我正在学习Go 1.18版本引入的泛型特性,希望实现一个可返回任意可哈希对象哈希值的函数,其理想行为与C++中的std::hash模板类似(例如std::hash<type>{}(x))。我已定义了Hashable接口:

type Hashable interface {int | string}

但不清楚后续如何推进。我需要为int、string等不同类型实现不同的哈希逻辑,且希望实现逻辑在编译时确定,以避免运行时类型检查的开销。请问是否可以通过Go泛型实现类似C++ STL中的这种哈希函数?


编辑补充:基准测试结果与泛型性能分析

我针对泛型方案做了基准测试,发现即使禁用类型推断,该方案的效率仍低于类型切换实现,推测Go泛型函数调用存在运行时开销。以下是测试代码及结果:

hash.go

package hash

import (
    "hash/fnv"
)

type Hashable interface {
    int | string
}

func Hash(x any) int {
    switch v := x.(type) {
    case int:
        return v
    case string:
        return stringHash(v)
    default:
        panic("hash function of this type not implemented")
    }
}

func intHash(x int) int {
    return x
}

func stringHash(x string) int {
    h := fnv.New32a()
    h.Write([]byte(x))
    return int(h.Sum32())
}

type Hint int
type Hstring string
type Hasher interface {
    Hash() int
}

func (x Hint) Hash() int {
    return int(x)
}

func (x Hstring) Hash() int {
    h := fnv.New32a()
    h.Write([]byte(x))
    return int(h.Sum32())
}

type HashableAlias interface {
    Hint | Hstring
    Hasher
}

func GetHash[T HashableAlias](h T) int {
    return h.Hash()
}

hash_test.go

package hash

import (
    "testing"
)

func BenchmarkHashStringTypeSwitch(b *testing.B) {
    s := "func (this *LRUCache) Get(key int) int {"
    for i := 0; i < b.N; i++ {
        Hash(s)
    }
}

func BenchmarkHashString(b *testing.B) {
    s := "func (this *LRUCache) Get(key int) int {"
    for i := 0; i < b.N; i++ {
        stringHash(s)
    }
}

func BenchmarkHashIntTypeSwitch(b *testing.B) {
    n := 123456
    for i := 0; i < b.N; i++ {
        Hash(n)
    }
}

func BenchmarkHashInt(b *testing.B) {
    n := 123456
    for i := 0; i < b.N; i++ {
        intHash(n)
    }
}

func BenchmarkGetHashInt(b *testing.B) {
    n := 123456
    for i := 0; i < b.N; i++ {
        GetHash(Hint(n))
    }
}

func BenchmarkGetHashIntHalfConvert(b *testing.B) {
    var n Hint = 123456
    for i := 0; i < b.N; i++ {
        GetHash(n)
    }
}

func BenchmarkGetHashIntMethod(b *testing.B) {
    n := 123456
    for i := 0; i < b.N; i++ {
        Hint(n).Hash()
    }
}

func BenchmarkGetHashIntNoInfer(b *testing.B) {
    n := 123456
    f := GetHash[Hint]
    for i := 0; i < b.N; i++ {
        f(Hint(n))
    }
}

func BenchmarkGetHashString(b *testing.B) {
    s := "func (this *LRUCache) Get(key int) int {"
    for i := 0; i < b.N; i++ {
        GetHash(Hstring(s))
    }
}

基准测试输出(go version go1.19.4 darwin/arm64)

BenchmarkExtendibleHashTable-10          9066850               148.8 ns/op
BenchmarkHashStringTypeSwitch-10        26299448                43.56 ns/op
BenchmarkHashString-10                  25259280                43.05 ns/op
BenchmarkHashIntTypeSwitch-10           1000000000               0.6236 ns/op
BenchmarkHashInt-10                     1000000000               0.3114 ns/op
BenchmarkGetHashInt-10                  552110401                2.109 ns/op
BenchmarkGetHashIntHalfConvert-10       576661430                2.125 ns/op
BenchmarkGetHashIntMethod-10            1000000000               0.3118 ns/op
BenchmarkGetHashIntNoInfer-10           560186821                2.119 ns/op
BenchmarkGetHashString-10               26585163                44.29 ns/op

内容的提问来源于stack exchange,提问作者Zacchaeus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 00:35:16