首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解Go的切片表示法

理解Go的切片表示法
EN

Stack Overflow用户
提问于 2018-07-28 22:08:26
回答 2查看 753关注 0票数 4

我正在浏览,模块让我思考,似乎每次你通过切片下界来修改视图时,切片的容量和长度都会减少。但是,正如前面所述,切片创建的底层数组不会被更改。

我将示例代码简化如下:

代码语言:javascript
复制
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 [],意思是这个片段现在完全没用了。

但是,数组是未更改的,数组仍然是(为了可视化):

代码语言:javascript
复制
[2, 3, 5, 7, 11, 13]

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

所以我的问题是,这是切片的副作用,还是预期的/首选的行为?第二,是否有办法将视图恢复到原来的水平?(显示[2, 3, 5, 7, 11, 13])

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-28 22:45:58

你好像很了解围棋片。

Go片被实现为struct

代码语言:javascript
复制
type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

它是底层数组的视图。

例如,

代码语言:javascript
复制
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)
}

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

输出:

代码语言:javascript
复制
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]

在没有对基础数组的任何元素的引用(指针)之前,将不会垃圾收集基础数组。

例如,

代码语言:javascript
复制
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
}

操场:IS7S3QE

输出:

代码语言:javascript
复制
s 6 6 [2 3 5 7 11 13] 0x10458000
t 6 6 [2 3 5 7 11 13] 0x10458000
p 0x10458000 2

阅读:

Go博客: Go片:用法和内部

Go博客:数组、切片(和字符串):“追加”的机制

Go程序设计语言规范切片类型切片表达式

票数 3
EN

Stack Overflow用户

发布于 2018-07-28 23:28:17

至于你的第二个问题,是的,你可以恢复原来,但只有非常黑暗的魔法反射和不安全。

代码语言:javascript
复制
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) //extract SliceHeader
arr := *(*[6]int)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s)).Data)) //restore array data

游乐场

它不能安全或可移植地使用,其表示形式可能在以后的版本中更改。

不要在生产中使用这个。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51575627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档