2016-09-23 58 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

相關問題