Golang 指向切片的指针

Posted

技术标签:

【中文标题】Golang 指向切片的指针【英文标题】:Golang pointer to a slice 【发布时间】:2020-07-26 15:08:15 【问题描述】:

我最近在做一个回溯问题,遇到了这个我无法理解的奇怪场景。这个问题与列出给定数组中所有可能的子集有关。这是代码sn-p:

func subsets(A []int) [][]int 
    sort.Ints(A)
    res, cur := [][]int, []int
    if len(A) == 0 
        return append(res, cur)
    
    subsetsUtil(A, 0, &res, cur)
    return res


func subsetsUtil(A []int, n int, res *[][]int, cur []int) 
    *res = append(*res, append([]int, cur...))
    for i := n; i < len(A); i++ 
        cur = append(cur, A[i])
        subsetsUtil(A, i+1, res, cur)
        cur = cur[:len(cur)-1]
    

这段代码 sn-p 给了我正确的答案,但如果我删除指向结果切片的指针,即

func subsets(A []int) [][]int 
    sort.Ints(A)
    res, cur := [][]int, []int
    if len(A) == 0 
        return append(res, cur)
    
    subsetsUtil(A, 0, res, cur)
    return res


func subsetsUtil(A []int, n int, res [][]int, cur []int) 
    res = append(res, append([]int, cur...))
    for i := n; i < len(A); i++ 
        cur = append(cur, A[i])
        subsetsUtil(A, i+1, res, cur)
        cur = cur[:len(cur)-1]
    

代码不起作用并返回一个空切片。据我了解,切片是通过引用而不是按值传递的,那么当我将指针传递给结果切片时,代码如何工作并给我正确的结果,但对于另一种情况,它返回给我一个空片?我错过了什么?

【问题讨论】:

请注意,您的代码没有使用数组——这些是切片。 Go 中的一切都是按值传递的,甚至是切片。请注意,切片值只是(可能共享的)支持数组的视图。参加 GO 切片之旅并阅读相关博客文章。 【参考方案1】:

这句话:“据我所知,切片是通过引用而不是通过值传递的”并不完全正确。切片不是纯引用类型,而是聚合类型,例如这个结构:

type IntSlice struct 
ptr *int
len, cap int

因此,每当按值传递切片时,都会对此结构进行复制,这与您传递的结构不同。

【讨论】:

感谢您的澄清。我实际上阅读了有关数组、切片(和字符串)的 go 博客文章:“附加”的机制,但我仍然不清楚为什么将某些东西分配给 1-D 切片可以在没有参考的情况下工作,但不能用于 2-D 切片。在这两种情况下,它都有指向数组第一个元素的指针。

以上是关于Golang 指向切片的指针的主要内容,如果未能解决你的问题,请参考以下文章

golang学习

golang基础篇

Golang Slice 总结

golang-101-hacks(12)——切片作为函数参数传递

GoLang中的切片扩容机制

golang Golang Snippet - 使用不安全指针进行切片变异