和数组不同的是,slice之间不能比较,我们不能使用==操作符来判断两个slice是否相等。
自己总结了下原因:
slice在源码中,其实是一个struct
,由三部分组成:指针,长度和容量。
type slice struct {
array unsafe.Pointer
len int
cap int
}
如果==使用的是浅度相等,只要两个slice的指针,长度和容量三个字段相等,那么两个slice就相等。但这样和数组不同的相等测试方法,会让人困惑。
func main() { // 两个数组相等 a1 := [3]int{1,2,3} a2 := [3]int{1,2,3} fmt.Println(a1 == a2) // true // 如果slice使用的是浅相等 a1 := []int{1,2,3} a2 := []int{1,2,3} fmt.Println(a1 == a2) // false,和数组的行为不同,造成困惑 }
如果==使用的是深度相等,和数组的行为保持一致,那也会有下面的问题。
正常情况下,将一个slice赋值给另一个slice时,我们只是复制上面的结构体,两个slice的指针都指向同一个底层数组。func main() { s1 := s0 s1[0] = 0 // 通过s1修改,会影响到s0 }
当将slice作为map的key时,我们遵循上面的slice复制规则,只会复制结构体内的指针,长度和容量,不会复制指针指向的底层数组,这是
浅拷贝
,map在对比两个key是否相等时,使用的会是浅度相等,这就会和深度相等矛盾。
下面有一个例子,如果能够使用slice做为map的key,不同的程序员对程序的输出会有不同的期望,造成困惑。
m := make(map[[]int]bool)
s0 := []int{6, 7, 8}
s1 := []int{6, 7, 8}
s2 := s0
m[s0] = true
s2[0] = 9
println(m[s0])
println(m[s1])
println(m[s2])
参考资料
Why can't Go slice be used as keys in Go maps pretty much the same way arrays can be used as keys?