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

Fil*_*und 0 concurrency hash dictionary go goroutine

我编写了这个函数来为我的测试用例生成随机唯一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
Run Code Online (Sandbox Code Playgroud)

为了测试它,我产生在不同的够程一堆从它的值,将其发送到主线程,这使结果在map[string]intmap[v] = map[v] + 1.没有对此映射的并发访问权限,它对主线程是私有的.

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

当我把它转换uidCounter成一个字符串时,我在一个键上发生了大量的碰撞.当我使用时strconv.FormatInt,我根本没有碰撞.

当我说一吨,我的意思是我刚刚1115919碰撞的价值[TestUuidIsUnique|?]出来的2227980生成值,即该值的50%,在同一个键冲突.价值观不相等.对于相同的源代码,我总是得到相同数量的冲突,所以至少它有点确定性,即可能与竞争条件无关.

我并不感到惊讶整数溢出rune会是一个问题,但我远不及2 ^ 31,这也无法解释为什么地图认为50%的值具有相同的密钥.此外,我不希望哈希冲突影响正确性,只影响性能,因为我可以遍历地图中的键,因此值存储在某处.

在输出中,所有符文都是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|?]"
...
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?那些作者是否认为这hash(a) == hash(b)意味着a == b字符串?或者我只是错过了一些愚蠢的事情?go test -race也没抱怨.

我在macOS上10.13.2,而且go version go1.9.2 darwin/amd64.

Cer*_*món 7

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

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