What do the terms pointer receiver and value receiver mean in Golang?

huangapple go评论88阅读模式
英文:

What do the terms pointer receiver and value receiver mean in Golang?

问题

我一直在遇到关于指针接收器的错误,所以我决定搜索一下这些术语的含义,并阅读了不同的来源和文档来了解指针接收器。例如:http://golang.org/doc/faq 和 http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go

尽管它们谈到了这些术语,但它们没有明确定义它们。从上下文来看,我认为它们之间的区别在于将变量定义为指针,如 *MyStruct vs MyStruct。虽然我对它们的区别不是100%确定,但我希望能够更正式、更深入地理解这些术语,特别是它们之间的区别(指针接收器和值接收器)。如果可能的话,提供一些简单的示例代码来展示它们在 Go 中的区别将会很棒!(这可能是真正理解这个问题所必需的)

例如,有一件让我困惑的事情是,指针和指针接收器之间有什么区别?值和值接收器之间有什么区别?术语“接收器”对这些概念有什么补充作用?

英文:

I've been getting errors from go saying stuff about pointer receivers and I decided to google what the terms mean and I read different sources and documentation talking about pointer receivers. For example: http://golang.org/doc/faq and http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go.

Though, eventhough they talk about these terms they failed to define them precisely. Though, from the context I think the difference between them are defining variables as pointers like *MyStruct vs MyStruct. Although, I am not 100% sure of their difference, I wanted to get a more official or solid understanding of the terms, specially their difference (pointer receiver and value receiver). If possible some simple example code showing their difference in go would be awesome! (and probably necessary to really understand this)

Like for example, something that is confusing me is, what is the difference between the term pointer and pointer receiver? or Value and value receiver? What does the term receiver add to these concepts?

答案1

得分: 5

由于你澄清了你对术语“接收器(receiver)”感到困惑,而不是指针/值的区别。在Go语言中,“接收器”指的是方法定义所在的值,用于接口的目的。你可以将接收器视为函数的第一个参数的特殊情况。

func (m MyStruct) DoStuff()

这被称为“值接收器(value receiver)”,它是在值MyStruct上定义的。从功能上讲,它与以下函数定义是相同的:

func DoStuff(m MyStruct)

不同之处在于:

使用“接收器”时,你可以像在许多面向对象语言中一样,使用“.”来调用函数:

m := MyStruct{} 
m.DoStuff() // 而不是 DoStuff(m)

类型作为接收器的方法集合定义了它实现的接口:

type DoesStuff interface {
    DoStuff()
}

func DoSomething(d DoesStuff) {
    d.DoStuff()
}

func main() {
    m := MyStruct{}
    DoSomething(m)
}

那么什么是指针接收器呢?它的定义如下:

func (m *MyStruct) DoOtherStuff()

区别在于指针和值之间的区别。尽管会发生一些微小的语义变化。Go语言会自动对指针进行取址和解引用(在大多数情况下),所以m := MyStruct{}; m.DoOtherStuff()仍然有效,因为Go会自动为你执行(&m).DoOtherStuff()(当然,你也可以使用m := &MyStruct{}; m.DoOtherStuff)。此外,接口是在指针上定义的,因此:

type DoesOtherStuff interface {
    DoOtherStuff()
}

func DoSomethingElse(d DoesOtherStuff) {
    d.DoOtherStuff()
}

func main() {
    m := MyStruct{}
    // DoSomethingElse(m)会失败,因为接口DoesOtherStuff是在指针接收器上定义的,而这里传入的是一个值
    DoSomethingElse(&m)
}

如果你仍然对何时使用指针接收器和变量接收器感到困惑,简短的答案是:可能是指针接收器。长答案已经被多次回答过了,但我会在这里提供一个链接1,因为在我的历史记录中很容易找到。

英文:

Since you clarified you're confused by the term receiver and not the pointer/value distinction. In Go "receiver" refers to the value a method is defined on, for purposes of interfaces. You can think of the receiver as a special case of the first argument to a function.

func (m MyStruct) DoStuff()

This is what's known as a "value receiver", it is defined on the value MyStruct. This is functionally identical to:

func DoStuff(m MyStruct)

Except:

With a "receiver" you call the function with ".", like in many OO languages:

 m := MyStruct{} 
 m.DoStuff() // as opposed to DoStuff(m)

The set of methods a type is a receiver on defines the interface it implements:

type DoesStuff interface {
    DoStuff()
}

func DoSomething(d DoesStuff) {
    d.DoStuff()
}

func main() {
    m := MyStruct{}
    DoSomething(m)
}

So what's a pointer receiver? It looks like this:

func (m *MyStruct) DoOtherStuff()

The difference is exactly the difference between a pointer and a value. Though minor semantic changes occur. Go will auto address and auto-dereference pointers (in most cases) so m := MyStruct{}; m.DoOtherStuff() still works since Go automatically does (&m).DoOtherStuff() for you. (Naturally, you're free to do m := &MyStruct{}; m.DoOtherStuff as well). Further, the interface is defined on the pointer, so:

type DoesOtherStuff interface {
    DoOtherStuff()
}

func DoSomethingElse(d DoesOtherStuff) {
    d.DoOtherStuff()
}

func main() {
    m := MyStruct{}
    // DoSomethingElse(m) will fail since because the interface
    // DoesOtherStuff is defined on a pointer receiver and this is a value
    DoSomethingElse(&m)
}

If you're still confused about when to use a pointer receiver versus a variable receiver, the short answer is: probably a pointer receiver. The long answer has been answered several times, but I'll link here simply because it was easy to find in my history.

huangapple
  • 本文由 发表于 2014年6月24日 23:48:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/24391062.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定