golang中slice处理遇到的一个关于引用的坑

ustb80 · · 484 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前两天在解扫地机器人算法的问题时,遇到一个坑

部分代码如下:

func move2(startPoint Point) [][]Point {
    allFootPrint := [][]Point{{startPoint}}
    for i := 0; i < N; i++ {
        allNewFootPrint := make([][]Point, 0)
        for len(allFootPrint) > 0 {
            curFootPrint := allFootPrint[len(allFootPrint)-1]
            allFootPrint = allFootPrint[:len(allFootPrint)-1]
            last := curFootPrint[len(curFootPrint)-1]
            for _, d := range directions {
                nextPoint := Point{last.X + d[0], last.Y + d[1]}
                if !inArray(nextPoint, curFootPrint) {
                    // 必须复制一份数据出来,否则会发生路径重复
                    newCurFootPrint := make([]Point, len(curFootPrint))
                    copy(newCurFootPrint, curFootPrint)

                    allNewFootPrint = append(allNewFootPrint, append(newCurFootPrint, nextPoint))
                }
            }
        }
        allFootPrint = allNewFootPrint
    }
    return allFootPrint
}

这处注释的地方非常关键,如果不复制出来,会导至allNewFootPrint中出现连续的两个相同路径,并且不是所有的路径都出问题,只会在一轮循环结束后,新一轮循环开始时才会出现,当时查了半天才查出问题。

现在把这个问题单独拎出来,分享给大家。

package main

import "fmt"

func main() {
    a := []int{1,2,3,4,5,6}
    x := a[:2]
    x = append(x, 9)
    fmt.Println(x)
    fmt.Println(a)
}

输出:

[1 2 9]
[1 2 9 4 5 6]

上面的操作很简单,就是从a切片里取出前2个,然后再追加一个数字9进去。
结果我们发现x是正确的,但a切片也随之发生了改动。
这说明x其实只是a切片的一个引用,对x的任何改动,都会影响到a。
这简直是挖了个天大的坑,机器人的问题也正是这里的问题。
只能copy出一个新的slice方能解决这个问题

package main

import "fmt"

func main() {
    a := []int{1,2,3,4,5,6}

    c := make([]int, 2)
    copy(c, a[:2])

    c = append(c, 9)
    fmt.Println(c)
    fmt.Println(a)
}

输出:

[1 2 9]
[1 2 3 4 5 6]

有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:ustb80

查看原文:golang中slice处理遇到的一个关于引用的坑

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

484 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传