我很想知道为什么,请给予我一点提示。
我想在res
中添加一个数组,res
是一个二维切片,所以我需要先进行转换,当我将数组转换为切片时,出现了一个bug。
// I need a map to remove duplicates
mm := map[[3]int]bool{}
mm[[3]int{-1, -1, 2}] = true
mm[[3]int{-1, -1, 2}] = true
mm[[3]int{-1, 0, 1}] = true
var res [][]int
for k, _ := range mm {
res = append(res, k[:])
}
fmt.Printf("the res is %v\n", res)
the res is [[-1 0 1] [-1 0 1]]
但结果不是我想要的。
然后我尝试性地修改了for循环
一个二个一个一个
现在结果是正确的,但是为什么呢?k[:]
和[]int{k[0],k[1],k[2]}
有什么不同?
2条答案
按热度按时间iszxjhcz1#
将循环更改为
你最初的循环声明了一个
[3]int
类型的变量k
,它在内存中有一个特定的位置,循环的每次迭代,Mapmm
中的一个不同的键都会被复制到那个变量中,到目前为止,一切都很好。当你用
k[:]
把它转换成一个切片时,它会创建一个切片头,指向数组k
。这里出错了--下一次循环时,k
的值会被覆盖。循环中创建的所有切片都指向内存中相同位置的相同后备数组k
。通过首先将
k
的值复制到一个在循环 * 内部 * 声明的变量,您可以为每个切片提供自己的支持数组,从而避免了这个问题。dauxcl2d2#
The Go Programming Language Specification
For语句
带range子句的For语句
迭代变量可以由“range”子句使用短变量声明(:=)的形式来声明。在这种情况下,它们的类型被设置为相应迭代值的类型,并且它们的范围是“for”语句的块;它们在每次迭代中被重用。
添加
k := k
语句会在每次迭代时使用局部变量k
隐藏重用的迭代变量k
。程序包干线
https://go.dev/play/p/4BdXzdThxXd