切片切片参考

我正在参观 Golang 网站,我正在尝试消化其中一个示例。目前还不清楚它是如何工作的:


package main


import "fmt"


func main() {

    s := []int{2, 3, 5, 7, 11, 13}

    printSlice(s)


    // Slice the slice to give it zero length.

    s = s[:0]

    printSlice(s)


    // Extend its length.

    s = s[:4]

    printSlice(s)


    // Drop its first two values.

    s = s[2:]

    printSlice(s)

}


func printSlice(s []int) {

    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)

}

输出是:


len=6 cap=6 [2 3 5 7 11 13]

len=0 cap=6 []

len=4 cap=6 [2 3 5 7]

len=2 cap=4 [5 7]

在第一个切片之后,s = s[:0]切片长度为0。然后是另一个切片s = s[:4]。虽然长度为 0,但这似乎有效。但是这是怎么发生的呢?底层数组不应该可以从访问吗s?


更让我困惑的是,下一次切片时,s = s[2:]我们切片的是 s 的旧值(有 4 个元素),而不是原始数组。


有人可以阐明这两种情况有什么区别吗?


智慧大石
浏览 92回答 2
2回答

慕村9548890

切片基本上是一个指向内存的指针,带有一些附加信息:1)当前使用的元素数量和2)容量,即它能占用的剩余长度。一开始我们创建了一个包含 6 个整数的切片,这使得 go 也创建了总大小为 6 的底层 int 数组。here is your memory locations with addresses (content does not matter here) *  *  *  *  *  *[0][1][2][3][4][5] ^ s points to the start of the memorylen(s) = 6cap(s) = 6接下来我们说:让这个slice'slen为0,这就是在位置0s = s[:0]处取一个长度为0的子切片。s注意s[0:0]是一样的,你可以省略第一个0。[0][1][2][3][4][5] ^ s still points to the start of the memorylen(s) = 0cap(s) = 6由于容量仍然相同,我们不妨将长度设为 4 s = s[:4]。 *  *  *  *[0][1][2][3][4][5] ^ s still points to the start of the memorylen(s) = 4cap(s) = 6然后我们通过做一个不在内存开头的子切片s = s[2:]。       *  *[0][1][2][3][4][5]       ^       s now points to the original address plus two!len(s) = 2cap(s) = 4

函数式编程

这是帮助我更好地理解这个概念的片段:切片是数组段的描述符。它由指向数组的指针、段的长度及其容量(段的最大长度)组成。切片不能超出其容量。尝试这样做会导致运行时恐慌,就像索引超出切片或数组边界时一样。同样,不能将切片重新切片到零以下以访问数组中较早的元素。如果数组中有更多元素,则可以扩展切片,但它不能访问切片 0 以下的元素。它是底层数组的窗口
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go