Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 为什么我的2D golang数组中填充了一行又一行的相同值?_Arrays_Go - Fatal编程技术网

Arrays 为什么我的2D golang数组中填充了一行又一行的相同值?

Arrays 为什么我的2D golang数组中填充了一行又一行的相同值?,arrays,go,Arrays,Go,我正在学习Go语言,并尝试执行以下示例(填充2D数组): --请参阅下面的代码 在本例中,我们假设使用值(基于我们选择的函数)填充uint8的2D数组,然后将其显示为照片/图案 在我的代码中,yy应该是一个[]]uint8数组,其中填充了一行[]uint8(xx) 对于模式/数据,我保持了它的简单性-对于yy(y轴)的每个索引,我增加了xx行中的值-因此数据应该输出一行0,然后是一行1,然后是一行2,等等 尽管根据下面第一条Println语句的输出(在我尝试填充二维数组yy时列在循环中),我的代

我正在学习Go语言,并尝试执行以下示例(填充2D数组): --请参阅下面的代码

在本例中,我们假设使用值(基于我们选择的函数)填充uint8的2D数组,然后将其显示为照片/图案

在我的代码中,
yy
应该是一个
[]]uint8
数组,其中填充了一行
[]uint8
xx

对于模式/数据,我保持了它的简单性-对于yy(y轴)的每个索引,我增加了xx行中的值-因此数据应该输出一行0,然后是一行1,然后是一行2,等等

尽管根据下面第一条Println语句的输出(在我尝试填充二维数组yy时列在循环中),我的代码似乎工作正常,但yy二维数组中存储的最终值都是255行!它以某种方式使用最后一个x轴行的值来表示所有内容

我想,我不是在做新的赋值,而是在某种程度上“指向”一行被过度写入的x轴数据,所以在最后,我得到了一个矩阵,其中填充了最后一行中的值

package main

import (
    "fmt"
    "golang.org/x/tour/pic"
)

func Pic(dx, dy int) [][]uint8 {


    //HERE I DYNAMICALLY CREATE THE ARRAYS BASED ON WHAT I WAS TAUGHT PREVIOUSLY
    //I UNDERSTAND THAT TECHNICALLY THESE MAY BE SLICES NOT ARRAYS ...
    //AND THUS MAYBE POINT SOMEWHERE AND DON'T ACTUALLY STORE ALL THE DATA (???)
    yy := make([][]uint8, dy)
    xx := make([]uint8, dx)

    for y := range yy {
        for x := range xx {
            xx[x] = uint8((y)) // FOR SIMPLICITY I MADE PATTERN ROW x = y
        }
        yy[y] = xx
        //THIS OUTPUT IS CORRECT; ROW OF 0's, ROW OF 1's, ROW OF 2's, ETC
        fmt.Println(y, yy[y])
    }

    for y := range yy {
        //THIS OUTPUT IS INCORRECT; ALL 255!
        //IT POPULATED ALL ROWS W/ VALUES FROM THE LAST LOOP
        fmt.Println(y, yy[y])
    }

    return yy

}

func main() {
    pic.Show(Pic)
}

注意:因为我正在调试,所以使用“fmt.Println()”可以取消我手中照片的显示(但不要担心这一点)。如果删除fmt.Println()调用,则可以获得要显示的照片(尽管带有错误/意外的数据)。

问题是
yy[y]=xx
不复制
xx
,它会为其分配一个引用

for y := range yy {
    for x := range xx {
        xx[x] = uint8((y))
    }

    // This is not a copy.
    yy[y] = xx

    fmt.Println(y, yy[y])
}
第一次迭代
y=0
。它将0写入所有
xx
,然后
yy[y]=xx
将对xx的引用分配给
yy[0]
,而不是
xx
的副本

循环的下一次迭代
y=1
。它将1写入所有
xx
,与之前相同的
xx
,这也改变了
yy[0]
中对
xx
的引用。然后,它将对
xx
的引用指定为
yy[1]
。重复256次

xx
yy[0]
yy[1]
yy[2]
等都引用相同的数据

当您最后打印
yy
时,实际上您只打印了
xx
256次。通过打印指针值
%p
,您可以清楚地看到这一点

fmt.Printf("%3s %p\n", "xx", xx);
for y := range yy {
    fmt.Printf("%03v %p\n", y, yy[y])
}

 xx 0xc420096000
000 0xc420096000
001 0xc420096000
002 0xc420096000
003 0xc420096000
004 0xc420096000
005 0xc420096000

解决方案是在循环内分配
xx
,因此每次循环迭代都分配一个新的
xx

for y := range yy {
    xx := make([]uint8, dx)

    for x := range xx {
        xx[x] = uint8((y))
    }

    // Still takes a reference to xx, but a different xx each time.
    yy[y] = xx

    fmt.Println(y, yy[y])
}

或者您可以复制
xx
,但这种方法更安全:不可能意外地重复使用相同的引用。

这是因为您(通过引用)将
xx
分配到
yy
中的所有位置(好像
yy:=[]uint8{xx,xx,xx,xx,…}

尝试为
yy
中的每个位置分配一个新的
xx

yy := make([][]uint8, dy)
for y := range yy {
    xx := make([]uint8, dx)

因为切片是引用类型(指针类型)。所以
yy[y]=xx
只是将具有相同底层数组的切片放入
yy
。要解决它,请使用
copy(yy[y],xx)
。好的,谢谢,让我试试这个。就像答案一样如上所述,在循环中使用make是一个更好的主意,因为它可以保存副本。我只是想用一行来解决您的问题。只需在循环中移动行:“xx:=…”。