【问题标题】:Functions in Go returns a new slice or a slice pointing to the underlying arrays of the first slice?Go 中的函数返回一个新切片还是指向第一个切片的底层数组的切片?
【发布时间】:2019-12-16 13:12:25
【问题描述】:

如果可能的话,我正在尝试让我的代码更具执行性以节省内存

我做了一些研究,但找不到关于这个具体案例的任何信息。

func createSlice() []int {
    return s[]int{1,2,3}
}

func main() {
    s2 := createSlice()
}

s2 会是一个全新的切片,有自己的底层数组,还是指向 s 的底层数组的切片?

【问题讨论】:

  • 您还没有找到有关切片如何工作的任何信息? blog.golang.org/go-slices-usage-and-internalstour.golang.org/moretypes/7golang.org/doc/effective_go.html#slicesgobyexample.com/slicess2 是切片头的副本,引用相同的底层数组。
  • 嗨 JimB,感谢您提供的资源!我读了其中一些,但我不明白它如何适用于我提到的案例。
  • 它适用于所有情况。切片值是包含长度、容量和指向底层数组的指针的标头。赋值复制值,因此您会获得切片头的副本,其中包含指向同一底层数组的指针。该赋值是函数参数还是函数返回值或其他任何内容都没有关系。
  • 谢谢阿德里安!帮助很大

标签: pointers go slice


【解决方案1】:

你必须知道 Go Slices 的 header。然后,您可以自己得到答案。

通过查看reflect.SliceHeader 类型来查看切片头中的内容:

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

实际上,Slice 的值是一个header,包含后备数组以及长度和容量。它包含一个指向实际存储元素的数组的指针。切片值不包含元素(与数组不同)。

所以,当一个切片被传递或返回时,一个副本将与指针一起从这个头传递或返回。该指针指向同一个后备数组。因此,如果您修改切片的元素,它也会修改支持的数组,因此所有切片(共享相同的支持数组)也会得到更改。

因此,当您将切片传递给函数时,将从该标头制作副本,包括指向同一个后备数组的指针。修改切片的元素意味着修改后备数组的元素,因此共享相同后备数组的所有切片都将“观察”更改。

请参阅博客https://blog.golang.org/go-slices-usage-and-internals

参考:Are golang slices passed by value?

【讨论】:

    猜你喜欢
    • 2012-11-10
    • 1970-01-01
    • 2023-01-08
    • 2018-04-22
    • 2022-01-25
    • 2015-05-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    相关资源
    最近更新 更多