一尘不染

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

go

我认为,一旦它被召唤出来,这将变得有点明显,但现在以下内容并未点击。

type Stack []interface{}

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

我有一个叫做Stack的类型,它是空接口的一部分。假定为空,则Push方法满足该接口。给定切片是引用类型,为什么不能仅按​​值传递“堆栈”接收器?此外,在上面的示例中,接收器作为指针传递,为什么附加的内置内置元素需要再次通过指针传递?

IE,鉴于分片是指向基础数组的引用指针,为什么不起作用?

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

阅读 229

收藏
2020-07-02

共1个答案

一尘不染

请参阅Go博客上的这篇文章。它详细解释了正在发生的事情,并完全回答了您的问题。

从“将切片 传递给函数 ”部分:

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

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

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

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

随着append要修改的片段头部。和

因此,如果要编写修改标头的函数,则必须将其作为结果参数返回

要么:

让函数修改切片头的另一种方法是将指针传递给它。

您似乎也对指针的使用感到困惑。见规格

对于类型T的操作数x,地址操作&x生成指向 T的类型 T的指针。

和:

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

因此,您的示例*stack = append(*stack, x)并不意味着您要传递指向的指针append,恰恰相反-
您要取消引用该指针以传递其指向的值。

2020-07-02