Go Slice - [:n] 和 [n:] 的区别
Go Slice - difference between [:n] and [n:]
Go Slice 问题,如果我遗漏了什么,请检查下面并评论。
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
s = s[1:]
fmt.Println(s)
s = s[2:]
fmt.Println(s)
s = s[5:]
fmt.Println(s)
}
输出:
[3 5 7 11 13]
[7 11 13]
panic: runtime error: slice bounds out of range
以上说得有道理。
func main() {
s := []int{2, 3, 5, 7, 11, 13}
s = s[:1]
fmt.Println(s)
s = s[:2]
fmt.Println(s)
s = s[:5]
fmt.Println(s)
}
输出:
[2]
[2 3]
[2 3 5 7 11]
这也应该从 s=s[:2] 得到数组越界恐慌吗?
Go 中的子切片允许您切片超出切片的末尾,只要它仍在底层数组的容量范围内。您不能在该切片的开始 之前切片 ,但只要您不超过最后分配的索引,就可以在它之后切片。
例如,s[3:]
然后 s[:3]
可以工作,但是 s[4:]
然后 s[:4]
会出现恐慌,因为您正在请求基础数组的索引 4 到 7 , 它只分配了索引 0-5.
这有点奇怪,但它确实允许您通过 slice = slice[:cap(slice)]
.
简单地最大化任何切片
https://play.golang.org/p/Gq5xoXc3Vd
language specification 对此进行了注释,顺便说一句。我在下面为您使用的简单切片符号解释了它(还有一个替代方法也指定了新切片的最大索引)。
For a string, array, pointer to array, or slice a, the primary expression a[low : high]
constructs a substring or slice.
The indices are in range if 0 <= low <= high <= cap(a),
otherwise they are out of range.
我只是想在阅读官方博客后分享我对此的看法:https://blog.golang.org/slices
这里是Golang博客中的sliceHeader:
type sliceHeader struct {
Length int
ZerothElement *byte
}
现在声明你的切片:
s := []int{2, 3, 5, 7, 11, 13}
我相信它会做类似的事情:
var array [6]int
slice := sliceHeader {
Length: 6,
ZerothElement: &array[0],
}
通过执行:s = s[:2]
,您有效地将 sliceHeader 的长度从 6 更改为 2,因此您的 sliceHeader 将如下所示:
slice := sliceHeader {
Length: 2,
ZerothElement: &array[0],
}
请注意,ZerothElement 仍指向内存中的同一位置。因此,我们可以通过简单地再次更改长度来将切片扩展回其原始形式s = s[:6]
。
现在,假设您没有执行 s = s[:2]
而是执行了 s = s[2:]
,您有效地完成的是通过从 Length 中减去 2 并将 ZerothElement 的两个索引向前移动来隐藏前两个元素,导致 sliceHeader 为:
slice := sliceHeader {
Length: 4,
ZerothElement: &array[2],
}
此时,您无法将切片恢复到其原始形式,因为无法将切片扩展到 ZerothElement 之外。好的,假设您可以访问 ZerothElement 之前的任何元素怎么办?然后我们的切片变得未定义,因为它可能是 array[0...4]
、array[1...5]
或 array[2...6]
。
是的,这就是为什么我认为 [n:] 和 [:n] 的行为不同。
Go Slice 问题,如果我遗漏了什么,请检查下面并评论。
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
s = s[1:]
fmt.Println(s)
s = s[2:]
fmt.Println(s)
s = s[5:]
fmt.Println(s)
}
输出:
[3 5 7 11 13]
[7 11 13]
panic: runtime error: slice bounds out of range
以上说得有道理。
func main() {
s := []int{2, 3, 5, 7, 11, 13}
s = s[:1]
fmt.Println(s)
s = s[:2]
fmt.Println(s)
s = s[:5]
fmt.Println(s)
}
输出:
[2]
[2 3]
[2 3 5 7 11]
这也应该从 s=s[:2] 得到数组越界恐慌吗?
Go 中的子切片允许您切片超出切片的末尾,只要它仍在底层数组的容量范围内。您不能在该切片的开始 之前切片 ,但只要您不超过最后分配的索引,就可以在它之后切片。
例如,s[3:]
然后 s[:3]
可以工作,但是 s[4:]
然后 s[:4]
会出现恐慌,因为您正在请求基础数组的索引 4 到 7 , 它只分配了索引 0-5.
这有点奇怪,但它确实允许您通过 slice = slice[:cap(slice)]
.
https://play.golang.org/p/Gq5xoXc3Vd
language specification 对此进行了注释,顺便说一句。我在下面为您使用的简单切片符号解释了它(还有一个替代方法也指定了新切片的最大索引)。
For a string, array, pointer to array, or slice a, the primary expression
a[low : high]
constructs a substring or slice. The indices are in range if 0 <= low <= high <= cap(a), otherwise they are out of range.
我只是想在阅读官方博客后分享我对此的看法:https://blog.golang.org/slices
这里是Golang博客中的sliceHeader:
type sliceHeader struct {
Length int
ZerothElement *byte
}
现在声明你的切片:
s := []int{2, 3, 5, 7, 11, 13}
我相信它会做类似的事情:
var array [6]int
slice := sliceHeader {
Length: 6,
ZerothElement: &array[0],
}
通过执行:s = s[:2]
,您有效地将 sliceHeader 的长度从 6 更改为 2,因此您的 sliceHeader 将如下所示:
slice := sliceHeader {
Length: 2,
ZerothElement: &array[0],
}
请注意,ZerothElement 仍指向内存中的同一位置。因此,我们可以通过简单地再次更改长度来将切片扩展回其原始形式s = s[:6]
。
现在,假设您没有执行 s = s[:2]
而是执行了 s = s[2:]
,您有效地完成的是通过从 Length 中减去 2 并将 ZerothElement 的两个索引向前移动来隐藏前两个元素,导致 sliceHeader 为:
slice := sliceHeader {
Length: 4,
ZerothElement: &array[2],
}
此时,您无法将切片恢复到其原始形式,因为无法将切片扩展到 ZerothElement 之外。好的,假设您可以访问 ZerothElement 之前的任何元素怎么办?然后我们的切片变得未定义,因为它可能是 array[0...4]
、array[1...5]
或 array[2...6]
。
是的,这就是为什么我认为 [n:] 和 [:n] 的行为不同。