Go方法集-带有接收者T的指针类型* T的调用方法
Go spec says:
The method set of any other type T consists of all methods with receiver type T. The method set of the corresponding pointer type *T is the set of all methods with receiver *T or T (that is, it also contains the method set of T).
I understand this as: T has its own method set, while *T has it own method set plus the method set of T, because it can dereference receiver *T to T and call the method. Therefore, we can call some method with receiver *T of variable type T.
So I decided to verify my logic:
package main
import (
"fmt"
"reflect"
)
type User struct{}
func (self *User) SayWat() {
fmt.Println(self)
fmt.Println(reflect.TypeOf(self))
fmt.Println("WAT
")
}
func main() {
var user User = User{}
fmt.Println(reflect.TypeOf(user), "
")
user.SayWat()
}
http://play.golang.org/p/xMKuLzUbIf
I am a bit confused. It looks like I can call methods "of *T" on T? I have a bit wider example http://play.golang.org/p/RROPMj534A, which confuses me too. Is there some vice versa type inference?
Am I missing something, or my logic is incorrect?
Thanks!
转到 spec 说: p>
任何其他类型T的方法集都包含接收者类型T的所有方法。相应指针类型的方法集 * T是带有接收者* T或T的所有方法的集合(也就是说,它也包含T的方法集合)。 p> blockquote>
我理解为: T有自己的方法集,而* T有自己的方法集加上T的方法集,因为它可以将接收者* T取消引用到T并调用该方法。 因此,我们可以使用变量类型T的接收者* T调用某些方法。 p>
所以我决定验证我的逻辑: p>
包 main import( “ fmt” “ reflect” ) type User struct {} func(self * User)SayWat(){ fmt.Println(self) fmt.Println(reflect.TypeOf(self)) fmt.Println(“ WAT ”) } func main(){ var user User = User {} fmt.Println (reflect.TypeOf(user),“ ”) user.SayWat() } code> pre>
http://play.golang.org/p/xMKuLzUbIf p>
我有点困惑 。 看来我可以在T上调用方法“ of * T”? 我有一个更广泛的示例 http://play.golang.org/p/RROPMj534A , 我也很困惑 反过来有类型推断吗? p>
我错过了什么吗,或者我的逻辑不正确? p>
谢谢! p>
You cannot call a method of *T
on T
, but the compiler is smart enough to take the reference of the variable for you, effectively calling
(&user).SayWat()
This is explained here:
Calls: A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().
To understand the difference, you can for instance take a return value (non-addressable):
func aUser() User {
return User{}
}
...
aUser().SayWat()
Fails with error:
prog.go:40: cannot call pointer method on aUser()
prog.go:40: cannot take the address of aUser()