我认为一旦它被叫到我就会有点明显,但是现在以下不是点击。
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)
}
答案 0 :(得分:7)
见article on the Go blog。它详细解释了正在发生的事情并完全回答了您的问题。
从将切片传递给函数
部分重要的是要理解即使切片包含指针,它本身也是一个值。在封面下,它是一个包含指针和长度的结构值。它不是指向结构的指针。
因此,您需要一个指针接收器,或者如果要使用append
修改它,则需要将切片作为值返回。
如果您只想修改切片的内容,只需按值传递切片:
即使切片标头按值传递,标头也包含一个 指向数组元素的指针,因此原始切片头和 传递给函数的头文件副本描述了相同的数组。 因此,当函数返回时,修改后的元素可以是 通过原始切片变量看到。
使用append
修改切片标头。和
因此,如果我们想编写一个修改标题的函数,我们必须这样做 将其作为结果参数返回
或者:
让函数修改切片标头的另一种方法是传递指向它的指针。
你似乎也对使用指针感到困惑。请参阅spec:
对于类型为T的操作数x,地址操作& x生成* T到x的指针。
和
对于指针类型* T的操作数x,指针间接* x表示由x指向的类型T的变量。
因此,您的示例*stack = append(*stack, x)
并不意味着您正在向append
传递指针,恰恰相反 - 您正在取消引用指针以传递它指向的值。
答案 1 :(得分:2)
您遇到的问题是append
返回对新切片的引用。除非是指针,否则不能更改函数接收器的值。
我建议的是制作一个包装结构:
type Stack struct{
data []interface{}
size int
}
func (s *Stack) Push(i interface{}){
s.data = append(s.data,i)
s.size++
}