刚开始浏览 gotour,遇到了关于 slice 默认章节的问题。
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
s = s[1:4]
fmt.Println(s) // [3 5 7]
fmt.Println(len(s)) // 3
s = s[:4]
fmt.Println(s) // [3 5 7 11]
fmt.Println(len(s)) // 4
}
我可以通过选择大于或等于前一个 slice 长度的索引来扩展右侧 slice 的长度。例如s[:4]
所以我可以到达条目 11
。但是当我使用 s[-1:]
向左扩展并到达入口 2
时,编译器给我错误 invalid slice index -1 (index must be非负数)
。
s=s[1:4]
执行后,是否可以将左侧的 slice 长度扩展到条目 2
?
最佳答案
首先,要回答您的问题,不,不可能使用负索引或访问该数据,除非保留原始 slice 的副本。
但是,这是一个有趣的问题,因为您已经指出了这里的不一致之处,这可能更多的是您要问的问题。如果您以 here 开头的 slice :
a := []int{2, 3, 5, 7, 11, 13}
fmt.Println(a,len(a),cap(a))
[2 3 5 7 11 13] 6 6
然后从中间取一片
b := a[1:2]
fmt.Println(b,len(b),cap(b))
[3] 1 5
如您所料,您不能访问超过该 slice len 的原始数据中的索引:
fmt.Println(b[3])
panic: runtime error: index out of range
您不能重新 slice 以从开始索引之前再次包含该数据:
d := b[-1:]
invalid slice index -1 (index must be non-negative)
但是您被允许在 len 到 cap 之后重新 slice 以再次包含该数据,这有点奇怪:
// This is beyond the length of b, you can't index those,
// but you can access them by reslicing
c := b[:5]
[3 5 7 11 13] 5 5
这有点不一致,因为对 slice 数据的大多数其他操作都受数据中的偏移量和长度限制,而不是上限和原始数据长度。但是,这在规范中明确说明,并且可能只是 slice 如何将 View 表示到原始数组上的人工制品,而不是提供对该数据的访问的有意设计决策。如果您可以返回原始存储可能会很好,因为它仍在内存中,但您似乎只能看到数组的结尾,而不是 slice 一次后的开始。来自 spec关于 slice 索引的限制:
For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length. A constant index must be non-negative and representable by a value of type int; for arrays or constant strings, constant indices must also be in range. If both indices are constant, they must satisfy low <= high. If the indices are out of range at run time, a run-time panic occurs.
为了安全起见,使用原始 slice 在数据上创建不同的 View 可能会更好,而不是依赖于这种行为。
关于go - 在左侧扩展 slice 长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46628683/