首页 文章

指针和切片参考类型 - 接收器

提问于
浏览
5

一旦它被叫到我,我认为这将是一个明显的,但现在以下不是点击 .

type Stack []interface{}

func (stack *Stack) Push(x interface{}) {
    *stack = append(*stack, x)
}

我有一个名为Stack的类型,它是一个空接口片 . 鉴于它是空的,Push方法满足接口 . 假设切片是一个引用类型,为什么“堆栈”接收器不能通过值传入?此外,在上面的例子中,接收器作为指针传递为什么追加内置需要再次通过指针传递?

IE为什么不能这样做,因为slice是一个指向底层数组的引用指针?

func (stack Stack) Push(x interface{}) {
    stack = append(stack, x)
}

2 回答

  • 7

    article on the Go blog . 它详细解释了正在发生的事情并完全回答了您的问题 .

    Passing slices to functions 部分:

    重要的是要理解即使切片包含指针,它本身也是一个值 . 在封面下,它是一个包含指针和长度的结构值 . 它不是指向结构的指针 .

    因此,您需要一个指针接收器,或者如果要使用 append 修改它,则需要将切片作为值返回 .

    如果您只想修改切片的内容,只需按值传递切片即可:

    即使切片标头按值传递,标头也包含指向数组元素的指针,因此原始切片标头和传递给函数的标头副本都描述了相同的数组 . 因此,当函数返回时,可以通过原始切片变量看到修改后的元素 .

    使用 append ,您正在修改切片标头 . 和

    因此,如果我们想编写一个修改 Headers 的函数,我们必须将它作为结果参数返回

    要么:

    使用函数修改切片标头的另一种方法是传递指向它的指针 .

    你似乎也对指针的使用感到困惑 . 见spec

    对于类型为T的操作数x,地址操作&x生成类型为* T到x的指针 .

    和:

    对于指针类型* T的操作数x,指针间接* x表示由x指向的类型T的变量 .

    因此,您的示例 *stack = append(*stack, x) 并不意味着您将指针传递给 append ,恰恰相反 - 您正在取消引用指针以传递它指向的值 .

  • 2

    您遇到的问题是 append 返回对新切片的引用 . 除非是指针,否则无法更改函数接收器的值 .

    我建议的是制作一个包装器结构:

    type Stack struct{
       data []interface{}
       size int
    }
    func (s *Stack) Push(i interface{}){
       s.data = append(s.data,i)
       s.size++
    }
    

相关问题