首页 > 解决方案 > Go 中的切片如何不被取消引用?

问题描述

我已将问题作为注释包含在代码中。

我在这里看到不一致。我们在这里做 3 片。在第一个切片 s = s[:0] 之后,s 应该始终指向 s[:0]。

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}
    printSlice(s)

    // Slice the slice to give it zero length.
    //1
    s = s[:0]
    printSlice(s) //after we do this, should not the var s always point to s[:0]?

    // Extend its length.
    s = s[:4]
    printSlice(s) //here, how is this s pointing back to original s? we just changed it to be s = s[:0]

    // Drop its first two values.
    s = s[2:]     //yet here we somehow refer to only the portion from s[:4]
    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 []         // slice s[:0]  
len=4 cap=6 [2 3 5 7]  // slice s[:4] - here we refer to the whole array s
len=2 cap=4 [5 7]      // slice s[2:] - here we refer not to the whole array s, but to the part we got from s[:4], which is contradiction to s[:0]

希望它不会太混乱。

标签: goslice

解决方案


切片是底层数组的视图。无论您重新切片它,它仍然是相同的底层数组。如果你取同一个数组的两个切片,它们也将具有相同的底层数组,例如: https: //play.golang.org/p/T-hYDWeo2TK

initial := []string{"foo", "bar", "baz"}
s1 := initial[:1]
initial[0] = "qux"
fmt.Println(s1)

[曲克斯]

Go 博客文章Go Slices: usage and internals中的大量示例对此进行了详细解释:

切片是数组段的描述符。它由指向数组的指针、段的长度及其容量(段的最大长度)组成。

因此,您可以继续制作具有不同长度/容量/起始索引但具有相同数组的不同切片。它们只是同一阵列上的不同视图。


推荐阅读