如何在Golang中实现与Kotlin一致的字符串哈希逻辑?
问题:Kotlin与Golang字符串哈希结果不一致的原因?
在服务A中,我使用如下Kotlin代码对字符串进行哈希处理:
fun String.toHash(): Long { var hashCode = this.hashCode().toLong() if (hashCode < 0L) { hashCode *= -1 } return hashCode }
我希望在服务B的Golang代码中复现该逻辑,以保证相同字符串得到完全一致的哈希值。我误以为Kotlin的哈希返回64位整数,因此编写了如下Golang代码:
func hash(s string) int64 { h := fnv.New64() h.Write([]byte(s)) v := h.Sum64() return int64(v) }
但单元测试时结果不一致,测试代码如下:
func Test_hash(t *testing.T) { tests := []struct { input string output int64 }{ {input: "papafritas", output: 1079370635}, } for _, test := range tests { got := hash(test.input) assert.Equal(t, test.output, got) } }
测试得到的结果为:7841672725449611742,与预期的1079370635不符,请问哪里出错了?
问题根源与解决方案
核心错误
你用错了哈希算法。Kotlin的String.hashCode()继承自Java的String.hashCode(),它是一个32位的哈希算法,并非FNV-64。你在Golang中误用了FNV-64哈希,自然会得到完全不同的结果。
Java/Kotlin String哈希规则
Java/Kotlin的字符串哈希计算逻辑是:
- 初始值
h = 0 - 遍历字符串每个字符
char c:h = 31 * h + c - 最终返回32位整数结果(可能为负)
你的Kotlin代码只是把这个32位哈希转成64位长整数,再取绝对值。
正确的Golang实现
按照上述规则,在Golang中复现该逻辑:
func hash(s string) int64 { h := int32(0) for _, c := range s { h = 31*h + int32(c) } // 转成int64并取绝对值 res := int64(h) if res < 0 { res = -res } return res }
验证测试用例
用这个实现测试"papafritas":
- 计算得到的32位哈希是
1079370635(正数),转成int64后取绝对值还是1079370635,与预期结果完全一致。
内容的提问来源于stack exchange,提问作者Matias Barrios
相关产品推荐
相关产品推荐

