【发布时间】:2022-07-03 04:00:34
【问题描述】:
多态函数(完整代码见here):
type Intf interface{
Do()
}
type Intf2 interface {
Intf
Do2()
}
func CallIntf[T Intf](intf T) {
intf.Do()
}
手动单形:
func CallIntf_mono(intf Intf) {
intf.Do()
}
实例化:
var intf2 Intf2
intf2 = &impl{}
CallIntf[Intf](intf2)
实例化汇编(包含对runtime.assertI2I()的调用):
LEAQ type."".impl(SB), AX
CALL runtime.newobject(SB)
MOVQ AX, ""..autotmp_13+24(SP)
LEAQ go.itab.*"".impl,"".Intf2(SB), BX
LEAQ type."".Intf(SB), AX
CALL runtime.convI2I(SB)
MOVQ AX, BX
MOVQ ""..autotmp_13+24(SP), CX
LEAQ ""..dict.CallIntf["".Intf](SB), AX
CALL "".CallIntf[go.shape.interface { Do() }_0](SB)
生成的单态函数 asm(包含对 runtime.assertI2I() 的调用):
TEXT "".CallIntf[go.shape.interface { Do() }_0](SB), DUPOK|ABIInternal, $32-24
MOVQ CX, "".intf+56(SP)
LEAQ type."".Intf(SB), AX
CALL runtime.assertI2I(SB)
MOVQ 24(AX), CX
MOVQ "".intf+56(SP), AX
CALL CX
MOVQ 24(SP), BP
ADDQ $32, SP
RET
手动单形asm(不调用runtime.assertI2I()):
TEXT "".CallIntf_mono(SB), ABIInternal, $16-16
MOVQ AX, "".intf+24(FP)
MOVQ BX, "".intf+32(FP)
MOVQ 24(AX), CX
MOVQ BX, AX
CALL CX
MOVQ 8(SP), BP
ADDQ $16, SP
RET
问题:为什么生成的单态函数使用runtime.assertI2I(),而手动单态函数没有?在什么情况下调用者会使用需要转换的类型?
【问题讨论】:
-
不太清楚你的意思。如果将 nil 作为参数传递,则 CallIntf_mono() 和 CallIntf[T Intf]() 都会发生恐慌。不过,Monomorph 会抛出更粗糙的 SIGSEGV。
-
是的,但我不明白它与问题有何关系。 CallIntf_mono() 和 CallIntf[T Intf]() 都出现恐慌,因此额外调用 runtime.assertI2I() 在这个意义上没有显着差异。