切片的下限和上限

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

low and high bounds of slice

问题

我的代码片段

package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	fmt.Println("检查 1:", s, len(s))
	
	s = s[1:4]
	fmt.Println("检查 2:", s, len(s))

	s = s[3:5]
	fmt.Println("检查 3:", s, len(s))

	s = s[1:]
	fmt.Println("检查 4:", s, len(s))
}

输出结果

检查 1: [2 3 5 7 11 13] 6
检查 2: [3 5 7] 3
检查 3: [11 13] 2
检查 4: [13] 1

我的预期输出结果

检查 1: [2 3 5 7 11 13] 6
检查 2: [3 5 7] 3
panic: 运行时错误: 切片索引超出范围 [3:5]

s = s[1:4] - 在这里,我们更新了切片变量 s,它现在包含 [3 5 7],s = s[3:5] 应该会产生 索引超出范围 的错误,因为新值的 s 中不存在索引 3 到 5。

但是,为什么输出结果是 [11 13]?

英文:

My code snippet

package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	fmt.Println("check 1: ",s, len(s))
	
	s = s[1:4]
	fmt.Println("check 2: ",s, len(s))

	s = s[3:5]
	fmt.Println("check 3: ",s, len(s))

	s = s[1:]
	fmt.Println("check 4: ",s, len(s))
}

Output

check 1:  [2 3 5 7 11 13] 6
check 2:  [3 5 7] 3
check 3:  [11 13] 2
check 4:  [13] 1

My Expected Output

check 1:  [2 3 5 7 11 13] 6
check 2:  [3 5 7] 3
panic: runtime error: slice bounds out of range [3:5]

s = s[1:4] - Here we updated slice variable s which now contains [3 5 7] and s = s[3:5] should give out of range error since the index 3 to 5 doesn't exist in the new value of s

Instead, why did the output print - [11 13]

答案1

得分: 4

切片容量(slice capacity)如果大于切片长度,可能会引起一些困惑。关键思想是切片是数组的一个视图。你不能访问超出切片边界的元素,但你可以重新切片并获得对底层数组的新视图。

初始时,切片长度和容量都是6。

在执行s = s[1:4]之后,切片长度变为3,容量变为5。你可以将这个切片重新切片为大于3个元素,并且仍然可以访问底层数组的元素。

因此,s[3:5]是有效的,并且等同于原始切片的[4:6]

英文:

The slice capacity, when it is larger than the slice length, can be source of some confusion. The key idea is that a slice is a view over an array. You cannot access beyond the slice bounds, but you can re-slice it and get a new view over the underlying array.

Initially, slice length and capacity are 6.

After s = s[1:4], the slice length is 3, and capacity is 5. You can re-slice this slice to be larger than 3 elements, and still access the elements of the underlying array.

So, s[3:5] is valid, and equivalent to the [4:6] of the original slice.

答案2

得分: 2

这是根据Go语言的切片规则。Go语言的切片与其他语言有些不同。当从切片或数组中取出一个切片时,它指向的是先前的数组或切片,而不是复制。

                                      {2,3, 5,           7, 11, 13} //长度为6
s = s[1:4] //长度为3,但它指向这里 ^ 并在这里结束 ^
           {2,3, 5,      7, 11,             13}
s = s[3:5] //它指向这里 ^ 并在这里结束 ^

所以如果你执行 s = s[3:6],它会因为索引超出边界而引发错误。

英文:

This is according to golangs slice rule. Golangs slice works little bit different than other language. When a slice is taken from a slice or array it points to previous array or slice rather than copying.

                                      {2,3, 5,           7, 11, 13} //length 6
s = s[1:4] //length 3 but it points here ^ and ends here ^
           {2,3, 5,      7, 11,             13}
s = s[3:5] // it points here ^ and ends here ^

so if you did s = s[3:6] it will panic for index out of boundary.

答案3

得分: 1

如在golang文档中提到的-切片(slice)不存储任何数据,它只是描述底层数组的一部分。切片有长度和容量两个属性。切片的长度是它包含的元素数量。切片的容量是底层数组中从切片的第一个元素开始计算的元素数量。可以使用len(s)和cap(s)表达式获取切片s的长度和容量。

尽管执行s[1:4]后长度为3,但容量为5,因此可以从底层数组中访问s[3:5]而不会出现索引错误。

请尝试以下代码片段以更好地理解:

package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	fmt.Printf("check 1: len=%d cap=%d %v\n", len(s), cap(s), s)

	s = s[1:4]
	fmt.Printf("check 2: len=%d cap=%d %v\n", len(s), cap(s), s)

	s = s[3:5]
	fmt.Printf("check 4: len=%d cap=%d %v\n", len(s), cap(s), s)

	s = s[1:]
	fmt.Printf("check 5: len=%d cap=%d %v\n", len(s), cap(s), s)
}

输出:

check 1: len=6 cap=6 [2 3 5 7 11 13]
check 2: len=3 cap=5 [3 5 7]
check 4: len=2 cap=2 [11 13]
check 5: len=1 cap=1 [13]
英文:

As mentioned in golang documentations - A slice does not store any data, it just describes a section of an underlying array.
A slice has both a length and a capacity.
The length of a slice is the number of elements it contains.
The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice.
The length and capacity of a slice s can be obtained using the expressions len(s) and cap(s).

Though the length is 3 after executing s[1:4] the capacity is 5 and hence you could access s[3:5] from underlying array without index out error

Tryout the below snippet for better understanding

package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	fmt.Printf("check 1: len=%d cap=%d %v\n", len(s), cap(s), s)

	s = s[1:4]
	fmt.Printf("check 2: len=%d cap=%d %v\n", len(s), cap(s), s)

	s = s[3:5]
	fmt.Printf("check 4: len=%d cap=%d %v\n", len(s), cap(s), s)

	s = s[1:]
	fmt.Printf("check 5: len=%d cap=%d %v\n", len(s), cap(s), s)
}

Output:

check 1: len=6 cap=6 [2 3 5 7 11 13]
check 2: len=3 cap=5 [3 5 7]
check 4: len=2 cap=2 [11 13]
check 5: len=1 cap=1 [13]

huangapple
  • 本文由 发表于 2023年7月25日 11:44:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76759315.html
匿名

发表评论

匿名网友

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

确定