go - 在左侧扩展 slice 长度

标签 go

刚开始浏览 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/

相关文章:

reflection - 为什么我不能使用反射来获取 slice 的地址?

go - 如何在 monorepo 中设置 protobuf、grpc 和 Go 模块?

go - 我如何编写一个函数代理,它采用一个转换为 func(...x) ...y 的接口(interface){},并将结果绑定(bind)到一个指针值?

objective-c - 从 Safari 显示 : Do you want to allow this page to open "(null)"? 启动的应用程序

sockets - 如果没有 EOF,从 Golang 中的服务器读取 Unix Socket 响应的最佳方法是什么

go - 如何在main.go中找到run函数的入口?

go-sdl2 第一次运行后不清除窗口表面

go - 如何排除列被选中

go - 编译应用程序时可以要求最低 Go 版本吗?

go - Golang 的默认值模式