arrays - 理解 Go 的 slice 符号

标签 arrays go garbage-collection slice

我正在经历 Go-tour 和 this模块让我开始思考,似乎每次通过 slice 下限修改 View 时, slice 的容量和长度都会减少。然而,如前所述, slice 创建的底层数组不会改变。

我将示例代码简化为:

package main

import "fmt"

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

    s = s[6:]
    fmt.Println(cap(s), len(s), s)
}

这会打印:0 0 [] 意味着这个 slice 现在完全没用了。

然而,数组没有改变,数组仍然是(为了可视化):

[2, 3, 5, 7, 11, 13]

并被 s 引用,这意味着它不会被垃圾收集。

所以我的问题是,这是 slice 的副作用还是这种预期/首选行为?其次,有没有办法将 View 恢复到原来的状态? (显示 [2, 3, 5, 7, 11, 13])

最佳答案

你似乎理解 Go slice 。


一个 Go slice 被实现为一个 struct:

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

这是底层数组的 View 。

例如,

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}
    fmt.Println("s", cap(s), len(s), s)

    t := s[cap(s):]
    fmt.Println("s", cap(s), len(s), s)
    fmt.Println("t", cap(t), len(t), t)

    t = s
    fmt.Println("s", cap(s), len(s), s)
    fmt.Println("t", cap(t), len(t), t)
}

Playground :https://play.golang.org/p/i-gufiJB-sP

输出:

s 6 6 [2 3 5 7 11 13]
s 6 6 [2 3 5 7 11 13]
t 0 0 []
s 6 6 [2 3 5 7 11 13]
t 6 6 [2 3 5 7 11 13]

在没有对底层数组的任何元素的引用(指针)之前,底层数组不会被垃圾回收。

例如,

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}
    fmt.Println("s", cap(s), len(s), s, &s[0])
    t := s
    // the slice s struct can be garbage collected
    // the slice s underlying array can not be garbage collected
    fmt.Println("t", cap(t), len(t), s, &t[0])
    p := &t[0]
    // the slice t struct can be garbage collected
    // the slice t (slice s) underlying array can not be garbage collected
    fmt.Println("p", p, *p)
    // the pointer p can be garbage collected
    // the slice t (and s) underlying array can be garbage collected
}

Playground :https://play.golang.org/p/PcB_IS7S3QE

输出:

s 6 6 [2 3 5 7 11 13] 0x10458000
t 6 6 [2 3 5 7 11 13] 0x10458000
p 0x10458000 2

阅读:

The Go Blog: Go Slices: usage and internals

The Go Blog: Arrays, slices (and strings): The mechanics of 'append'

The Go Programming Language Specification : Slice typesSlice expressions

关于arrays - 理解 Go 的 slice 符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51575627/

相关文章:

c - 访问C中的外部分配空间

unit-testing - 如何为单元测试模拟标准包函数

php - 如果我有循环引用,我可以触发 PHP 垃圾收集自动发生吗?

go - 如何在 X 小时后有效地调用函数?

garbage-collection - 在 D 中制作结构的堆副本

pointers - 防止 F# 中的垃圾收集器移动对象

c++ - 将数组传递给函数

javascript - Jquery $.each 循环处理数组

mysql extract_json 数组中的值

html - 显示来自 Golang Controller 的数据