指针变量上的方法为什么有效,而其他情况下则无效?

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

Why do methods on pointers work when the pointer is a variable, but not otherwise?

问题

当运行以下代码时:

package main

import (
	"fmt"
)

type Bar struct {
	name string
}

func (foo Bar) testFunc() {
	fmt.Println(foo.name)
}

func doTest(pointer *Bar) {
	pointer.testFunc() // 在指针上运行`testFunc`(尽管它期望的是`Bar`类型的值,而不是`*Bar`类型)
}

func main() {
	var baz Bar = Bar{
		name: "Johnny Appleseed",
	}

	doTest(&baz) // 将`baz`的指针发送给`doTest()`
}

输出结果为:Johnny Appleseed。我本以为在指针上调用testFunc()会出错。

之后,我尝试将doTest(&baz)替换为&baz.testFunc()。然后我收到了错误信息:

tmp/sandbox667065035/main.go:24: baz.testFunc() used as value

为什么我只有在直接调用baz.testFunc()而不是通过另一个函数调用时才会出错?调用doTest(&baz)&baz.testFunc()不是做了完全相同的事情吗?因为doTest(pointer *Bar)只是调用了pointer.testFunc()

Playground 1 (doTest(&baz))

Playground 2 (&baz.testFunc())

英文:

When running the following code:

package main

import (
	"fmt"
)

type Bar struct {
	name string
}

func (foo Bar) testFunc() {
	fmt.Println(foo.name)
}

func doTest(pointer *Bar) {
	pointer.testFunc() // run `testFunc` on the pointer (even though it expects a value of type `Bar`, not `*Bar`)
}

func main() {
	var baz Bar = Bar{
		name: "Johnny Appleseed",
	}

	doTest(&baz) // send a pointer of `baz` to `doTest()`
}

The output reads: Johnny Appleseed. I would have thought I would have encountered an error for calling testFunc() on a pointer.

After that, I tried switching out doTest(&baz) for &baz.testFunc(). Then I received the error:

tmp/sandbox667065035/main.go:24: baz.testFunc() used as value

Why do I only get the error when calling baz.testFunc() directly instead of through another function? Wouldn't calling doTest(&baz) and &baz.testFunc() do the exact same thing, as doTest(pointer *Bar) simply calls pointer.testFunc()?

Playground 1 (doTest(&baz))

Playground 2 (&baz.testFunc())

答案1

得分: 2

这是因为自动解引用method values

与选择器一样,对于使用指针的值接收器的非接口方法的引用,将自动解引用该指针:pt.Mv 等同于 (*pt).Mv。

对于第二行,你出现了这个错误,是因为你对 testFunc 的结果取了地址,而 testFunc 并没有返回任何值。
你尝试做的是:

(&baz).testFunc()

这样可以正常工作。

英文:

It's because of automatic derefencing of method values

> As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.

For the second line, you have this error because you take the address of the result of testFunc which doesn't return any value.
What you tried to do is the following:

(&baz).testFunc()

which works as expected

huangapple
  • 本文由 发表于 2017年1月17日 02:02:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/41682427.html
匿名

发表评论

匿名网友

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

确定