普通网友 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 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?