Ili*_*oly 3 binding static interface dynamic 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()") }
Run Code Online (Sandbox Code Playgroud)
假设:
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)
Run Code Online (Sandbox Code Playgroud)
因此,当从type A- > 转换时interface B,如果A满足B则不需要断言,并且可以在编译时生成itable.如果您在不需要的情况下使用断言,那么情况如何:
var x Xer = Foo{}
empty := x.(interface{})
Run Code Online (Sandbox Code Playgroud)
在这种情况下会发生什么?如果有人能为我澄清这个很好的话.
我不知道接口的静态绑定或接口的动态绑定是什么.语言规范从未提及过这样的术语.我假设您的意思是在编译时进行类型检查并在运行时进行类型检查.有了这些假设,您的所有示例都是AFAICS,都是正确的.它归结为一个简单的模式(相关语言规范部分的精简版):
.(T))都在运行时进行类型检查.这也回答了"在这种情况下会发生什么?" .
也就是说,编译器可以自由地优化它可以在编译时证明类型已知且赋值兼容的情况.但这只是一个不能依赖的实现细节 - 因为它可能不是其他符合规范的实现的情况.
实际上gc编译器有(IINM)这样的优化,甚至是相反的意义.它可以说'不可能的类型断言',它可以在编译时证明类型断言将失败.
要扩展jnml的答案,请6g生成类型断言.
empty := x.(interface{})
Run Code Online (Sandbox Code Playgroud)
扩展到:
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)
Run Code Online (Sandbox Code Playgroud)
为了澄清这里发生的事情,在第34行中,InterfaceTypeof of interface{}被加载到堆栈的第一个值.35-36线和37-38把标签和数据值的x
压入堆栈.然后堆栈准备好调用runtime.assertI2E,它只是将基础类型和数据分配给返回值.编译器知道您正在分配一个空接口,因此调用assertI2E:I2E代表接口到Eface(空接口),因此不需要检查方法.唯一的限制assertI2E是声明的值必须是接口.
但是,如果您正在执行x.(Xer),runtime.assertI2I则会调用,然后检查方法是否实现了接口.
| 归档时间: |
|
| 查看次数: |
1224 次 |
| 最近记录: |