go map的value为切片时的注意事项

22 阅读1分钟

今天在刷题的时候发现了一个奇怪的go map奇怪的地方,于是记录下来
如果想要实现一个哈希表,然后这个哈希表能够通过拉链法解决地址冲突
我们可以通过以下方式实现

m := make(map[int][]int)

我们可以对哈希表进行操作

m[1] = []int{1}
if val, ok := m[1]; ok {
        val = append(val, 3)
        m[1] = append(m[1], 2)
}
fmt.Println(m[1])

打印结果为

map[1:[1 2]]

val看起来跟m[1]指向的不是同一个地址空间,可能是操作了某个副本?
我们打印一下地址

m := make(map[int][]int)
m[1] = []int{1}
if val, ok := m[1]; ok {
        fmt.Printf("%p\n", m[1])
        fmt.Printf("%p\n", val)
        val = append(val, 3)
        m[1] = append(m[1], 2)
        fmt.Printf("%p\n", m[1])
        fmt.Printf("%p\n", val)
}
fmt.Println(m[1])

结果发现一开始地址是相同的

0xc000016098
0xc000016098
0xc0000160e0
0xc0000160d0

接下来我们使用切片的指针作为value

m := make(map[int]*[]int)
m[1] = &[]int{1}
if val, ok := m[1]; ok {
        fmt.Printf("%p\n", m[1])
        fmt.Printf("%p\n", val)
        *val = append(*val, 3)
        *m[1] = append(*m[1], 2)
        fmt.Printf("%p\n", m[1])
        fmt.Printf("%p\n", val)
}
fmt.Println(m[1])

结果发现地址完全一致

0xc000008078
0xc000008078
0xc000008078
0xc000008078
&[1 3 2]