3

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{})

この場合はどうなりますか?誰かが私のためにこれを明確にすることができれば、それは素晴らしいことです.

4

2 に答える 2

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 行目でInterfaceTypeofinterface{}がスタックの最初の値にロードされます。35 ~ 36 行目と 37 ~ 38 行目は、タブとデータ値x スタックに置きます。これで、スタックはruntime.assertI2Eを呼び出す準備が整いました。これは、基になる型とデータを戻り値に割り当てるだけです。コンパイラは、空のインターフェイスに割り当てていることを認識しているため、assertI2E:への呼び出しI2Eは Interface to Eface (Empty Interface) を表しているため、メソッドのチェックは必要ありません。強制される唯一の制限assertI2Eは、アサートされる値がインターフェイスでなければならないということです。

ただし、実行しているx.(Xer)場合は、メソッドがインターフェイスを実装しているかどうかを確認runtime.assertI2Iするために呼び出されます。

于 2013-04-11T15:41:53.370 に答える