2013-04-11 126 views
3

Go使用動態和靜態綁定。從我的理解,如果你需要使用類型斷言,那麼它是動態的。我想驗證我的假設。Go界面:靜態與動態綁定

type Xer interface { 
    X() 
} 

type XYer interface { 
    Xer 
    Y() 
} 

type Foo struct{} 
func (Foo) X() { println("Foo#X()") } 
func (Foo) Y() { println("Foo#Y()") } 

假設:

foo := Foo{} 

// static: Foo -> XYer 
var xy XYer = foo 

// static: XYer -> Xer 
var x Xer = xy 

// static: Xer -> interface{} 
var empty interface{} = x 

// dynamic: interface{} -> XYer 
xy2 := empty.(XYer) 

// dynamic: XYer -> Foo 
foo2 := xy2.(Foo) 

所以從type A轉換時 - >interface B,如果A滿足B那麼你並不需要一個斷言,並且可以在編譯時產生的itable。如果您在不需要的地方使用斷言的情況如何:

var x Xer = Foo{} 
empty := x.(interface{}) 

在這種情況下會發生什麼情況?如果有人能爲我澄清這很好。

+0

爲什麼不看看它輸出的組件呢? – cthom06 2013-04-11 15:31:07

+1

@ cthom06因爲我太笨了。 – 2013-04-11 15:35:24

+1

[另請參閱](http://research.swtch.com/interfaces)。 – kostix 2013-04-12 08:05:12

回答

5

要延長jnml的答案,不過6g生成一個類型的斷言。

empty := x.(interface{}) 

被擴展爲:

0034 (dumb.go:19) MOVQ $type.interface {}+0(SB),(SP) 
0035 (dumb.go:19) LEAQ 8(SP),BX 
0036 (dumb.go:19) MOVQ x+-32(SP),BP 
0037 (dumb.go:19) MOVQ BP,(BX) 
0038 (dumb.go:19) MOVQ x+-24(SP),BP 
0039 (dumb.go:19) MOVQ BP,8(BX) 
0040 (dumb.go:19) CALL ,runtime.assertI2E+0(SB) 
0041 (dumb.go:19) MOVQ 24(SP),BX 
0042 (dumb.go:19) MOVQ BX,empty+-16(SP) 
0043 (dumb.go:19) MOVQ 32(SP),BX 
0044 (dumb.go:19) MOVQ BX,empty+-8(SP) 

爲了闡明這裏發生了什麼,在管線34的interface{}InterfaceType加載到堆的 第一個值。 35-36行和37-38提出的tab and data valuesx 到堆棧中。該堆棧然後準備好調用runtime.assertI2E, 它簡單地將基礎類型和數據分配給返回值。編譯器知道 你分配到一個空的接口,因此調用assertI2EI2E代表接口Eface(空接口),所以沒有檢查的方法是必要的。 assertI2E強制執行的唯一限制是 聲明的值必須是接口。

但是,如果你正在做x.(Xer)runtime.assertI2I會一直叫,然後checks如果 方法實現的接口。

+0

哇,這是一個很棒的答案!謝謝! – 2013-04-11 16:57:10

5

我不知道什麼是靜態的接口綁定或動態的接口綁定。語言規範從來沒有提到這樣的術語。讓我假設你的意思是在編譯時檢查類型並在運行時檢查類型。有了這個假設,你的所有例子,AFAICS,都是正確的。歸結爲一個簡單的模式(相關語言規範部分的精簡版本):

  • 所有賦值都是在編譯時檢查類型。
  • 所有類型斷言(.(T))的類型在運行時檢查。

這也回答了「在這種情況下會發生什麼?」

這就是說,編譯器就可以優化的情況下它可以在編譯時,該類型是已知的,轉讓兼容證明。但這只是一個不能依賴的實現細節 - 因爲它可能不是其他規範符合實現的情況。

其實GC編譯器(IINM)這樣的優化,甚至在相反的意義。它可以在編譯時證明類型斷言失敗的地方可以說'不可能類型斷言'。

+0

我剛剛讀完[我的](http://research.swtch.com/interfaces)。它表示方法表是在運行時生成的。但是,如果在編譯時對類型進行賦值(對於接口變量),我認爲它可能會在編譯時爲這些接口生成表。 – 2013-04-11 15:42:21

+0

第三段從底部http://www.airs.com/blog/archives/277 – 2013-04-11 15:59:05