Arrays Go Slice-[:n]和[n:]之间的差异
去切片的问题,请检查下面,并评论,如果我遗漏了什么Arrays Go Slice-[:n]和[n:]之间的差异,arrays,go,slice,Arrays,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] 恐慌:
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]
恐慌:运行时错误:切片边界超出范围
上述观点是有道理的
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://code>然后s[:3]
可以工作,但是s[4://code>然后s[:4]
将死机,因为您请求的是底层数组的索引4到7,该数组只分配了索引0-5
这有点奇怪,但它确实允许您通过执行slice=slice[:cap(slice)]
来最大化任何切片
顺便说一句,注释说明了这一点。我在下面对您使用的简单切片表示法进行了解释(还有一种替代方法,它还指定了新切片的最大索引)
对于字符串、数组、指向数组的指针或切片,主表达式a[low:high]
构造一个子字符串或切片。
如果0Go中的子扫描允许您在切片结束后进行切片,只要它仍在基线阵列容量的范围内,则索引在范围内。您不能在片段开始之前进行切片,但只要不超过最后分配的索引,就可以在片段开始之后进行切片
例如,s[3://code>然后s[:3]
可以工作,但是s[4://code>然后s[:4]
将死机,因为您请求的是底层数组的索引4到7,该数组只分配了索引0-5
这有点奇怪,但它确实允许您通过执行slice=slice[:cap(slice)]
来最大化任何切片
顺便说一句,注释说明了这一点。我在下面对您使用的简单切片表示法进行了解释(还有一种替代方法,它还指定了新切片的最大索引)
对于字符串、数组、指向数组的指针或切片,主表达式a[low:high]
构造一个子字符串或切片。
如果指数在0范围内,我只是想在阅读官方博客后分享我的想法:
以下是Golang博客中的标题:
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]
,您有效地将切片头的长度从6更改为2,因此切片头将如下所示:
slice := sliceHeader {
Length: 2,
ZerothElement: &array[0],
}
请注意,zerothement仍然指向内存中的相同位置。因此,只需再次更改长度,我们就可以将切片扩展回其原始形式s=s[:6]
现在,假设您没有执行s=s[:2]
,而是执行了s=s[2:]
,您实际执行的是通过从长度中减去2并向前移动Zerothement两个索引来隐藏前两个元素,从而产生一个切片头:
slice := sliceHeader {
Length: 4,
ZerothElement: &array[2],
}
此时,您无法将切片恢复为其原始形式,因为无法将切片扩展到zerothement之外。好吧,假设你可以访问零点之前的任何元素呢?然后,我们的切片变得未定义,因为它可能是数组[0…4]
,数组[1…5]
,或数组[2…6]
所以是的,这就是为什么我认为[n:]和[:n]的行为不同。我只是想在阅读官方博客后分享我的想法:
以下是Golang博客中的标题:
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]
,您有效地将切片头的长度从6更改为2,因此切片头将如下所示:
slice := sliceHeader {
Length: 2,
ZerothElement: &array[0],
}
请注意,zerothement仍然指向内存中的相同位置。因此,只需再次更改长度,我们就可以将切片扩展回其原始形式s=s[:6]
现在,假设您没有执行s=s[:2]
,而是执行了s=s[2:]
,您实际执行的是通过从长度中减去2并向前移动Zerothement两个索引来隐藏前两个元素,从而产生一个切片头:
slice := sliceHeader {
Length: 4,
ZerothElement: &array[2],
}
此时,您无法将切片恢复为其原始形式,因为无法将切片扩展到zerothement之外。好吧,假设你可以访问零点之前的任何元素呢?然后,我们的切片变得未定义,因为它可能是数组[0…4]
,数组[1…5]
,或数组[2…6]
是的,这就是为什么我认为[n:]和[:n]的行为不同。谢谢,我的问题是w.r.t赋值,当我们做s=s[:n]时,我的想法是s被新的片覆盖,而旧数组中的\slice实际上丢失了。对我来说这似乎有点不直观。啊,不,相同的底层数组。从根本上说,切片只是一个3字结构,具有指向底层数组的指针、整数长度和整数容量。当您进行子切片时,您可以根据需要使用更新的字段更改切片“头”(或创建一个新的头)。执行s=s[:n]
时,所做的只是将切片头的“长度”值更改为n
。仍然指向相同的基础阵列,仍然具有相同的容量,因此您可以再次将其扩展到该容量。如果您要制作基础阵列的副本(即,有一个新的切片指向完全不同的阵列,但其中包含相同的数据),则需要手动执行,逐个索引,或使用内置函数,它做切片的深度复制。编辑:仅深度复制到阵列级别。如果您的数组存储点