W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
普通的函數(shù)調(diào)用跟C語言中的調(diào)用方式基本上是一樣的,除了多值返回的一些細(xì)微區(qū)別,見前面章節(jié)。
根據(jù)Go語言文檔,對象的方法調(diào)用相當(dāng)于普通函數(shù)調(diào)用的一個語法糖衣。
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
表達(dá)式
T.Mv
得到一個函數(shù),這個函數(shù)等價于Mv但是帶一個顯示的接收者作為第一個參數(shù),也就是
func(tv T, a int) int
下面這些調(diào)用是等價的:
t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
可以看了一下方法調(diào)用用生成的匯編代碼:
type T int
func (t T) f() {
fmt.Println("hello world!\n")
}
func main() {
var v T
v.f()
return
}
將它進(jìn)行匯編:
go tool 6g -S test.go
得到的匯編代碼是:
0044 (sum.go:15) TEXT main+0(SB),$8-0
0045 (sum.go:15) FUNCDATA $0,gcargs·1+0(SB)
0046 (sum.go:15) FUNCDATA $1,gclocals·1+0(SB)
0047 (sum.go:16) MOVQ $0,AX
0048 (sum.go:17) MOVQ AX,(SP)
0049 (sum.go:17) CALL ,T.f+0(SB)
0050 (sum.go:18) RET ,
從這段匯編代碼中可以看出,方法調(diào)用跟普通函數(shù)調(diào)用完全沒有區(qū)別,這里就是把v作為第一個參數(shù)調(diào)用函數(shù)T.f()。
在Go中沒有繼承,但是有結(jié)構(gòu)體嵌入的概念。將一個帶方法的類型匿名嵌入到另一個結(jié)構(gòu)體中,則這個結(jié)構(gòu)體也會擁有嵌入的類型的方法。
這個功能是如何實現(xiàn)的呢?其實很簡單。當(dāng)一個類型被匿名嵌入結(jié)構(gòu)體時,它的方法表會被拷貝到嵌入結(jié)構(gòu)體的Type的方法表中。這個過程也是在編譯時就可以完成的。對組合對象的方法調(diào)用同樣也僅僅是普通函數(shù)調(diào)用的語法糖衣。
接口的方法調(diào)用跟上述情況略有不同,不同之處在于它是根據(jù)接口中的方法表得到對應(yīng)的函數(shù)指針,然后調(diào)用的,而前面是直接調(diào)用的函數(shù)地址。
對象的方法調(diào)用,等價于普通函數(shù)調(diào)用,函數(shù)地址是在編譯時就可以確定的。而接口的方法調(diào)用,函數(shù)地址要在運行時才能確定。將具體值賦值給接口時,會將Type中的方法表復(fù)制到接口的方法表中,然后接口方法的函數(shù)地址才會確定下來。因此,接口的方法調(diào)用的代價比普通函數(shù)調(diào)用和對象的方法調(diào)用略高,多了幾條指令。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: