golang slice [:]与最后一个元素匹配

时间:2018-06-06 12:24:54

标签: go

我正在研究golang中的示例程序,如下所示

package main

import (
    "fmt"
)

type thing [2]byte

func walk(things []thing, idx int) []byte {
    var match []byte
    for i, thing := range things {
        if i == idx {
            match = thing[:]
        }
    }
    return match
}


func main() {
    ta := []thing{ thing{'W','A'}, thing{'O','R'} }
    m := walk(ta, 0)

    tb := []thing{ thing{'C','A'}, thing{'W','Y'}, thing{'N','V'} }
    n := walk(tb, 1)

    fmt.Printf("m = %s\n", m)
    fmt.Printf("n = %s\n", n)
}

输出结果为:

m = OR
n = NV

我不知道为什么会出现这种情况,因为type thing [2] byte是一个大小为2的数组,而ta是类型[]的东西。

现在使用[] [] byte

编写相同的代码
package main

import (
    "fmt"
)

func walk(things [][]byte, idx int) []byte {
    var match []byte
    for i, thing := range things {
        if i == idx {
            match = thing[:]
        }
    }
    return match
}

func main() {
    ta := [][]byte{[]byte{'W', 'A'}, []byte{'O', 'R'}}
    m := walk(ta, 0)

    tb := [][]byte{[]byte{'C', 'A'}, []byte{'W', 'Y'}, []byte{'N', 'V'}}
    n := walk(tb, 1)

    fmt.Printf("m = %s\n", m)
    fmt.Printf("n = %s\n", n)
}

输出

m = WA
n = WY

我对这些不同的切片行为感到困惑? 当ta[:]ta is type thing []byte相同时打印ta[:] when ta is [][]byte

2 个答案:

答案 0 :(得分:2)

在一种情况下,个人thing是一个数组([2]byte),而在另一种情况下,它是一个切片([]byte)。在第一种情况下,您将数组切片为match,这会为您提供一个指向循环迭代变量的新切片。在第二种情况下,您将重新切片现有切片,因此即使在循环更改了局部切片变量之后,您的新切片也会指向该切片的基础数组。

因为你的循环在你找到你的匹配后继续运行,你找到你的匹配,切片,然后继续迭代,改变本地循环迭代器的值。如果你这样做了:

    if i == idx {
        return thing[:]
    }

相反,问题消失了:https://play.golang.org/p/Uq4DbEGlGX8

答案 1 :(得分:2)

两种情况 相同。

在第一种情况中,您使用的是[][2]byte(数组切片),而不是[][]byte(切片切片)。

var match []byte
for i, thing := range things { // (2) change array on each iteration
    fmt.Printf("Thing %v", thing)
    if i == idx {
        match = thing[:] // (1) slice refers to array   
    }
}
return match // (3) here match slice refers to the last item of things

此处的解决方案之一是在break之后添加match = thing[:]语句。它结束循环,match将引用预期的数组。

为了澄清这里的实际问题,问题是您正在创建一个切片,该切片引用在每个 n-iteration 中被覆盖的数组,其中包含对应的 2字节数组切片的第n个元素。 因此,如果您不停止迭代,切片将获得最后一个元素的值

使用for .. := range“隐藏”这个事实。我想如果你用for i;i<n;i++编写相同的代码,你可以更好地理解实际发生的事情:https://play.golang.org/p/z3hCskZ9ezV