我很想知道为什么,请给我一点提示。
我想在
res
中附加一个数组,res
是一个二维切片。所以我需要先转换。
当我将数组转换为切片时,出现错误。
// 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循环
for k, _ := range mm {
//res = append(res, k[:])
res = append(res, []int{k[0], k[1], k[2]})
}
the res is [[-1 0 1] [-1 -1 2]]
现在结果是对的,但是为什么呢?
k[:]
和 []int{k[0],k[1],k[2]}
有什么区别?
将循环更改为
for k, _ := range mm {
j := k
res = append(res, j[:])
}
您的原始循环声明了一个类型为
k
的变量 [3]int
,它在内存中有一个特定的位置。循环的每次迭代,都会将来自 map mm
的不同键复制到该变量。到目前为止,一切都很好。
当您使用
k[:]
将其转换为切片时,它会创建一个切片标头,points 到数组 k
。这里出了问题——循环的下一次迭代,k
的值被覆盖。在循环中创建的所有切片都指向内存中相同位置的相同后备数组k
。
通过首先将
k
的值复制到在循环中内部 声明的变量,您为每个切片提供了自己的后备数组,从而避免了这个问题。
对于带有范围子句的语句
迭代变量可以使用短变量声明(:=)的形式由“range”子句声明。在这种情况下,它们的类型被设置为各自迭代值的类型,它们的范围是“for”语句的块;它们在每次迭代中都会重复使用。
添加
k := k
语句将重复使用的迭代变量 k
与每次迭代的局部变量 k
隐藏在一起。
包主
import "fmt"
func main() {
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
fmt.Println(mm)
var res [][]int
for k, _ := range mm {
k := k
res = append(res, k[:])
}
fmt.Println(res)
}
https://go.dev/play/p/4BdXzdThxXd
map[[-1 -1 2]:true [-1 0 1]:true]
[[-1 -1 2] [-1 0 1]]