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()

http://play.golang.org/p/HOTKiiOK7S