使用指向Golang中结构的指针将方法转换为函数

时间:2016-09-23 06:48:09

标签: go

我读了一些奇怪的代码,它们将一个方法转换为一个函数,该函数的第一个参数是指向该方法结构的指针。

我写了一个例子来证明它:

package main

import "fmt"

type fooS struct{}

func (s *fooS) fooF(fooArg interface{}) {
    fmt.Println("fooF: ", fooArg)
}

type wowS struct {
    callback func(s *fooS, fooArg interface{})
}

func main() {
    wow := new(wowS)
    wow.callback = (*fooS).fooF // strange
    wow.callback(nil, 123)
}

Golang Playground Link

示例的语法很奇怪,但没有错误。

任何人都可以告诉我这些代码是如何运作的,或者给我一份关于它们的官方文件吗?

感谢:)

1 个答案:

答案 0 :(得分:7)

Method expressions

  

如果M位于T类型的方法集中,T.M是一个函数,   可以作为常规函数调用,其参数与M前缀相同   通过另一个参数,即方法的接收者。

MethodExpr    = ReceiverType "." MethodName .
ReceiverType  = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
     

考虑使用两个方法T的结构类型Mv,其接收方为。{   键入TMp,其接收者的类型为*T

type T struct {
  a int
}
func (tv  T) Mv(a int) int         { return 0 }  // value receiver
func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver

var t T
     

表达式

T.Mv
     

产生一个等于Mv的函数,但显式接收器为   它的第一个论点;它有签名

func(tv T, a int) int
     

可以使用显式接收器正常调用该函数,因此   这五个调用是等价的:

t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
     

同样,表达式

(*T).Mp 
     

产生一个表示带签名

的Mp的函数值
func(tp *T, f float32) float32
     

对于具有值接收器的方法,可以使用a派生函数   显式指针接收器,所以

(*T).Mv
     

产生一个代表Mv并带有签名

的函数值
func(tv *T, a int) int
     

这样的函数通过接收器间接创建值   作为接收者传递给基础方法;方法没有   覆盖在函数调用中传递其地址的值。

     

最后一种情况,指针接收器的值接收器功能   方法,是非法的,因为指针接收器方法不在   值类型的方法集。

     

使用函数调用调用从方法派生的函数值   句法;接收器作为呼叫的第一个参数提供。   也就是说,在f := T.Mv的情况下,f被调用为f(t, 7)而不是t.f(7)。至   构造一个绑定接收器的函数,使用函数文字   或方法价值。

     

从接口方法派生函数值是合法的   类型。结果函数采用了明确的接收器   界面类型。

见:
Go - difference between parameter and receiver
Is there a performance penalty for passing "this" by value in Go methods?
differences between pointer and value slice in for-range loop