2016-09-23 30 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 ")" . 

は、受信機タイプ*Tである2つの受信 タイプTである方法、Mv、およびMpと構造体型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へしかし 最初の引数として、明示的な受信機と同等の機能が得られます。同様

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 

機能をもたらす:それはそう これらの5つの呼び出しは等価であり、その関数が、明示的な受信機で正常に呼び出されてもよい

func(tv T, a int) int 

署名を有します署名付きMpを表す値

func(tp *T, f float32) float32 
値レシーバと方法について

、一方がそう

(*T).Mv 

署名

func(tv *T, a int) int 

このような機能のインダイレクトでMvを表す関数値をもたらす、 明示ポインタ受信機と関数を導出することができますレシーバを介して の値を作成して、受信側のメソッドに渡します。このメソッドは、 が関数呼び出しで渡されるアドレスの値を上書きしません。

最後のケースでは、ポインタ受信者メソッドが値型のメソッドセットにないため、ポインタ受信者 メソッドの受信者関数は不正です。

メソッドから派生した関数値は、関数呼び出し 構文で呼び出されます。受信者はコールの第1引数として提供されます。 つまり、f := T.Mvを指定すると、f(t, 7)ではなく、t.f(7)としてfが呼び出されます。 受信者をバインドする関数を作成するには、関数リテラル またはメソッド値を使用します。

インターフェイスのメソッド タイプから関数値を派生させることは正当です。結果の関数は、その インターフェイスタイプの明示的な受信者をとります。


とを参照してください。
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

関連する問題