英文:
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]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论