Go语言中对数组的子切片使用内置的range函数时,行为不一致。

huangapple go评论85阅读模式
英文:

Go's built-in range on a sub-slice of an array has incongruent behavior

问题

为什么我们不能使用内置的range来指定给定数组索引的下限,但我们可以指定索引的上限?

给定一个int切片:

array := []int{4, 76, -29, 3, 9, 223, 0, -3, -44, 76, 3, 98, 62, 144}

我想遍历该切片,但不包括前两个元素。

我可以使用for循环来实现:

for i := 2; i < len(array); i++ {
    fmt.Printf("%d ", array[i])
}

但是不能使用内置的range来实现:

for i := range array[2:] {
    fmt.Printf("%d ", array[i])
}

奇怪的是,我可以在上限范围内排除元素,像这样:

for i := range array[:5] {
    fmt.Printf("%d ", array[i])
}

Go Playground上运行它。

为什么会这样呢?

英文:

Why can't we use the built range to dictate the lower-end of given array's index, but we can specify the index's upper range?

Given a slice of int:

array := []int{4, 76, -29, 3, 9, 223, 0, -3, -44, 76, 3, 98, 62, 144}

I want to range over the slice, excluding the first two elements.

I can do this with a for-loop:

for i := 2; i &lt; len(array); i++ {
		fmt.Printf(&quot;%d &quot;, array[i])
	}

But can't with the built-in range:

for i := range array[2:] {
		fmt.Printf(&quot;%d &quot;, array[i])
	}

Strangely enough, i can exclude elements on the upper-range, like so:

for i := range array[:5] {
		fmt.Printf(&quot;%d &quot;, array[i])
	}

Run it on Go Playground

Why is this?

答案1

得分: 2

它是有效的,你只是看错了切片。

表达式 array[2:] 是一个新的切片,它从 array 的第二个元素开始。该切片的第一个元素是原始切片的第二个元素。按照以下方式修改代码,你就会看到结果:

for i, value := range array[2:] {
    fmt.Printf("%d ", value)
}

i 的取值范围是从 0 到 len(array)-2。

英文:

It does work, you are simply looking at the wrong slice.

The expression array[2:] is a new slice that starts from the 2'nd element of the array. The 0'th element of that slice is the 2nd element of the original slice. Do this, and you'll see:

for i,value := range array[2:] {
        fmt.Printf(&quot;%d &quot;, value)
}

The values for i range from 0 to len(array)-2.

答案2

得分: 2

表达式array[2:]求值为新的切片值。问题在于应用程序假设新切片中的元素与array中对应的元素具有相同的索引。

以下是解决该问题的几种方法。

使用range值:

for _, v := range array[2:] {
   fmt.Printf("%d ", v)
}

索引到新切片:

s := array[2:]
for i := range s {
   fmt.Printf("%d ", s[i])
}

当像array[:5]这样从末尾切片时,新切片中的元素与array中对应的元素具有相同的索引。

英文:

The expression array[2:] evaluates to new slice value. The problem is that the application assumes that the elements in the new slice have the same index as the corresponding element in array.

Here are a couple of approaches for addressing the problem.

Use the range value:

for _, v := range array[2:] {
   fmt.Printf(&quot;%d &quot;, v)
}

Index into the new slice:

s := array[2:]
for i := ranges s {
   fmt.Printf(&quot;%d &quot;, s[i])
}

When slicing from the end as in array[:5], the elements in the new slice have the same index as the corresponding elements in array.

huangapple
  • 本文由 发表于 2021年11月5日 09:23:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/69847690.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定