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)

所以当从A型转换时 – >接口B,如果A满足B,则不需要断言,并且可以在编译时生成itable.如果您在不需要的情况下使用断言,那么情况如何:

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

在这种情况下会发生什么?如果有人能为我澄清这个很好的话.

最佳答案
为了扩展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行中,接口{}的InterfaceType被加载到
堆栈的第一个值.第35-36行和第37-38行是x的tab and data values
到堆栈上.然后堆栈准备好调用runtime.assertI2E,
它只是将基础类型和数据分配给返回值.编译器知道这一点
您正在分配一个空接口,因此调用assertI2E:I2E代表接口到Eface(空接口),因此不需要检查方法. assertI2E强制执行的唯一限制是
断言的值必须是接口.

但是,如果你正在做x.(Xer),那么runtime.assertI2I就会被调用,然后就是checks
方法实现了接口.

转载注明原文:Go接口:静态绑定和动态绑定 - 代码日志