2016-09-23 115 views
1

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

我写一个例子来说明吧:

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

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

任何人都可以告诉我这些代码如何工作或给我一个关于他们的官方文件吗?

谢谢:)

回答

5

Method expressions

M如果在T类型的方法集,T.M是一个函数,它是 可调用与相同的参数M前缀 常规功能通过另一个参数即方法的接收者。

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

考虑两种方法,Mv,其接收器是 类型T的,和Mp,其接收器是*T类型的结构类型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 

对于具有值接收器的方法,就可以得出一个函数与一个 明确的指针接收器,所以

(*T).Mv 

产生表示Mv与签名

func(tv *T, a int) int 

这种函数indirects的函数值通过接收方创建一个值为 作为接收方传递给底层的方法;该方法不覆盖 覆盖其地址在函数调用中传递的值。

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

从函数派生的函数值通过函数调用 语法来调用;接收者作为呼叫的第一个参数被提供。 也就是说,给定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

相关问题