Dictionary golang内置映射和字符串键的哈希冲突?

Dictionary golang内置映射和字符串键的哈希冲突?,dictionary,go,hash,concurrency,goroutine,Dictionary,Go,Hash,Concurrency,Goroutine,我编写此函数是为了为我的测试用例生成随机唯一id: func uuid(t *testing.T) string { uidCounterLock.Lock() defer uidCounterLock.Unlock() uidCounter++ //return "[" + t.Name() + "|" + strconv.FormatInt(uidCounter, 10) + "]" return "[" + t.Name() + "|" + str

我编写此函数是为了为我的测试用例生成随机唯一id:

func uuid(t *testing.T) string {
    uidCounterLock.Lock()
    defer uidCounterLock.Unlock()

    uidCounter++
    //return "[" + t.Name() + "|" + strconv.FormatInt(uidCounter, 10) + "]"
    return "[" + t.Name() + "|" + string(uidCounter) + "]"
}

var uidCounter int64 = 1
var uidCounterLock sync.Mutex
为了测试它,我在不同的goroutine中从它生成一组值,将它们发送到主线程,通过执行
map[v]=map[v]+1
将结果放入
map[string]int
。没有对该映射的并发访问,它对主线程是私有的

var seen = make(map[string]int)
for v := range ch {
    seen[v] = seen[v] + 1
    if count := seen[v]; count > 1 {
        fmt.Printf("Generated the same uuid %d times: %#v\n", count, v)
    }
}
当我将
uidCounter
转换为字符串时,一个键上会发生大量冲突。当我使用strconv.formatt时,我一点冲突都没有

当我说一吨时,我的意思是我只是得到了
1115919
[TestUuidIsUnique]的冲突|�]
2227980
生成的值中,即50%的值在同一个键上发生冲突。这些值不相等。对于相同的源代码,我总是得到相同的冲突次数,因此至少它在某种程度上具有确定性,即可能与竞争条件无关

我并不奇怪
符文中的整数溢出会成为一个问题,但我离2^31还远着呢,这也不能解释为什么映射认为50%的值都有相同的键。此外,我不希望哈希冲突影响正确性,只会影响性能,因为我可以在映射中迭代键,所以值存储在那里ewhere

在输出中,所有打印的符文都是
0xEFBFBD
。它的位数与最高有效unicode代码点的位数相同,但实际上也不匹配

Generated the same uuid 2 times: "[TestUuidIsUnique|�]"
Generated the same uuid 3 times: "[TestUuidIsUnique|�]"
Generated the same uuid 4 times: "[TestUuidIsUnique|�]"
Generated the same uuid 5 times: "[TestUuidIsUnique|�]"
...
Generated the same uuid 2047 times: "[TestUuidIsUnique|�]"
Generated the same uuid 2048 times: "[TestUuidIsUnique|�]"
Generated the same uuid 2049 times: "[TestUuidIsUnique|�]"
...
这到底是怎么回事?围棋的作者们是否认为
hash(a)==hash(b)
意味着
a==b
对于字符串?或者我只是遗漏了一些愚蠢的东西?
go test-race
也没有抱怨


我在macOS上
10.13.2
,并且
go版本go1.9.2 darwin/amd64

无效符文的字符串转换返回一个包含unicode替换字符的字符串:�".


使用strconv包将整数转换为文本。

哈希表直接比较存储桶中的值,问题是您不断添加相同的字符串:
“[TestUUIDSUnique|�]“
@JimB当然可以,但为什么我会得到相同的字符串?为什么它会停在那个确切的符文上?它甚至可以在操场上复制:无效符文的字符串转换返回一个包含unicode替换字符的字符串:”�“@CeriseLimón啊,一定是这样!你想写下来作为答案吗?@FilipHaglund:将无效符文转换为字符串总是返回
“\ufffd”
“\xef\xbf\xbd”