Golang数组使用中的常见问题与解决方案
Golang数组使用中的常见问题与解决方案 // 为什么打印出的 ‘array’ 所有槽位都只填充了最后追加的条目?
package main
import “fmt”
var array [][]int
var pos []int
func main() {
pos = append(pos, 0)
pos = append(pos, 0)
array = make([][]int, 0, 100)
count := 0
for i := 0; i < 2; i++ {
for j := 0; j < 2; j++ {
pos[0] = j
pos[1] = 0
fmt.Println(“i=”, i, “j=”, j, “count=”, count, “pos=”, pos)
array = append(array, pos)
fmt.Println(“appending pos=”, pos, “to array”)
fmt.Println(“just added”, array[count])
count++
}
}
fmt.Println(“size is”, len(array))
fmt.Println(“array”, array)
}
// 谢谢!
更多关于Golang数组使用中的常见问题与解决方案的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
因为切片本身就是一个指针,所以实际上你是在操作 pos 中的同一个指针。
// array = append(array, pos)
array = append(array, []int{pos[0], pos[1]})
// or
array = append(array, append(make([]int, 0, len(pos)), pos...))
// or other...
更多关于Golang数组使用中的常见问题与解决方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
切片是一个引用,因此当你创建切片 pos 并添加两个元素时,它只被创建一次,当你分配新值时,你实际上是分配到了同一个地址。
var pos []int // 这里 pos 是 nil
pos = append(pos, 0)
pos = append(pos, 0)
因此,你需要在循环内部创建 pos 切片。
for j := 0; j < 2; j++ {
pos := make([]int, 2)
pos[0] = j
pos[1] = 0
fmt.Printf("address of pos %p \n", &pos)
fmt.Println("i=", i, "j=", j, "count=", count, "pos=", pos)
array = append(array, pos)
fmt.Println("appending pos=", pos, "to array")
fmt.Println("just added", array[count])
count++
}
要检查你切片的地址,只需
fmt.Printf("address of pos %p \n", &pos)
这是一个典型的切片引用问题。pos 切片在内存中只有一个底层数组,每次修改 pos[0] 和 pos[1] 都是在修改同一个底层数组。当执行 array = append(array, pos) 时,实际上是将 pos 切片的引用(指针)追加到 array 中,而不是复制其当前值。
因此,array 中所有元素都指向同一个 pos 切片,最终所有槽位都显示 pos 最后被修改的值 [1 0]。
解决方案是每次追加时创建 pos 的副本:
package main
import "fmt"
func main() {
var array [][]int
array = make([][]int, 0, 100)
count := 0
for i := 0; i < 2; i++ {
for j := 0; j < 2; j++ {
// 每次循环创建新的切片
pos := []int{j, 0}
fmt.Println("i=", i, "j=", j, "count=", count, "pos=", pos)
array = append(array, pos)
fmt.Println("appending pos=", pos, "to array")
fmt.Println("just added", array[count])
count++
}
}
fmt.Println("size is", len(array))
fmt.Println("array", array)
}
或者使用 copy 函数显式复制:
package main
import "fmt"
var array [][]int
var pos []int
func main() {
pos = make([]int, 2)
array = make([][]int, 0, 100)
count := 0
for i := 0; i < 2; i++ {
for j := 0; j < 2; j++ {
pos[0] = j
pos[1] = 0
fmt.Println("i=", i, "j=", j, "count=", count, "pos=", pos)
// 创建副本
posCopy := make([]int, len(pos))
copy(posCopy, pos)
array = append(array, posCopy)
fmt.Println("appending pos=", pos, "to array")
fmt.Println("just added", array[count])
count++
}
}
fmt.Println("size is", len(array))
fmt.Println("array", array)
}
两个解决方案都会输出正确的结果:
array [[0 0] [1 0] [0 0] [1 0]]
这是因为每次追加的都是独立的数据副本,而不是同一个切片的引用。

