普通网友 2018-02-07 01:42
浏览 53
已采纳

为什么我的2D Golang数组中的每一行都填充相同的值?

I am taking a tour of the Go language and am trying to do the following example (populating 2D arrays): https://tour.golang.org/moretypes/18 -- see the code below...

In the example we are supposed to populate a 2D array of uint8 with values (based on a function of our choice), then displaying these as a photo/pattern.

In my code, yy should be a [][]uint8 array populated with single rows of []uint8 (xx).

For the pattern/data I kept it simple - with each index of yy (y-axis), I increase the values placed in rows of xx - so the data should output a row of 0's, then a row of 1's, then a row of 2's, etc.

Although my code appears to work correctly based on the output of the first Println statement below (listed inside the loop as I attempt to populate the 2D array yy), the final values stored in the yy 2d array are all rows of 255! It's somehow using the value of the last x-axis row for everything.

I think somehow instead of making new value assignments I am somehow "pointing" to a single row of x-axis data that's being over-written, so at the end I get a matrix filled with the values that went in that final row.

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)
}

Note: Because I am debugging, use of "fmt.Println()" abrogates the display of the photo in my hands (but don't worry about that aspect). If you delete the fmt.Println() calls you can get the photo to display (albeit with the wrong/unexpected data).

  • 写回答

2条回答 默认 最新

  • duanguanya3052 2018-02-07 01:57
    关注

    The problem is yy[y] = xx does not copy xx, it assigns a reference to it.

    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])
    }
    

    The first iteration y = 0. It writes 0 to all of xx, then yy[y] = xx assigns a reference to xx to yy[0], not a copy of xx.

    The next iteration of the loop y = 1. It writes 1 to all of xx, the same xx as before, which also alters the reference to xx in yy[0]. It then assigns a reference to xx as yy[1]. Repeat 256 times.

    xx, yy[0] and yy[1] and yy[2] and so on all refer to the same data.

    When you print yy at the end, you're really just printing xx 256 times. You can see this clearly by printing the pointer value, %p.

    fmt.Printf("%3s %p
    ", "xx", xx);
    for y := range yy {
        fmt.Printf("%03v %p
    ", y, yy[y])
    }
    
     xx 0xc420096000
    000 0xc420096000
    001 0xc420096000
    002 0xc420096000
    003 0xc420096000
    004 0xc420096000
    005 0xc420096000
    

    The solution is to allocate xx inside the loop, so a new xx is allocated each loop iteration.

    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])
    }
    

    Or you can copy xx, but this approach is safer: there's no possibility to accidentally reuse the same reference.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 用hfss做微带贴片阵列天线的时候分析设置有问题
  • ¥50 我撰写的python爬虫爬不了 要爬的网址有反爬机制
  • ¥15 Centos / PETSc / PETGEM
  • ¥15 centos7.9 IPv6端口telnet和端口监控问题
  • ¥120 计算机网络的新校区组网设计
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 海浪数据 南海地区海况数据,波浪数据
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等