Lazyこの広告は、90日以上更新していないブログに表示しています。2016-08-08Go言語のインターフェースの値は、メモリ上でどう表現されているかGo前回の記事では、Go言語のスライスと文字列の値がメモリ上でどう表現されているか見てみました。今回はインターフェースへの理解を深めるべく、インターフェースの値がメモリ上でどう表現されているかGDBでみてみます。インターフェースの値まず、インターフェースの構造体は次のようになっています(runtime/runtime2.go#L71)。unsafe.Pointer}itabは、インターフェースの型情報や、メソッドの配列等を保持する構造体です。この構造体の定義は、後でGDBを動かすときに確認します。dataはインターフェースを実装した構造体へのポインタを保持しています。実際の値をGDBで見てみます。今回は例として次のようなコードを使います。64bit、Goのバージョンが1.6.2です。Print(ns)}GoのバイナリをGDBから扱いやすくするため、次のようにgcflagsオプションをつけてビルドします。interface.goGDBを起動して、インターフェースの値をみてみます。以降の文字は後で書き足しています。0x000000c82000a300ポイントとしては、(1)で確認したNums構造体へのポインタ値0x000000c82000a300が、(2)で確認したCalc構造体の値に含まれていることです。ここから、iface構造体のdataフィールドには、Nums構造体へのポインタが格納されていることがわかります。次は、iface構造体のtabフィールドが指すitab構造体を確認してみます。itab構造体は次のように定義されています(runtime/runtime2.go#L514)。sized}各フィールドは次のような意味です。インターフェースの型についての情報。インターフェースを実装した型についての情報。他のitab構造体へのポインタ。itab構造体の値をハッシュテーブルにキャッシュするときに使用。_typeの型がインターフェースを正しく実装できているかどうかを示します。メソッドが足りない場合はフラグが立ちます。アラインメント用です。正確には、インターフェースを実装した型がもつメソッドへのポインタの配列。この定義では長さ1の配列になっていますが、実際はメソッド数分の配列になっています。itab構造体の値を生成するときに、足りない分は補ってメモリ確保されます。この構造体の値のうち、funフィールドの値をGDBで確認してみます。先程の続きから実行していきます。0x000000102444c748(3)、(4)から確認できる通り、配列の1番目にはNums構造体のAddメソッドへのポインタ、配列の2番目にはNums構造体のMulメソッドへのポインタが格納されています。ちなみに今回は割愛しましたが、interや_typeフィールドについては、runtime/type.goで構造体の定義を確認できます。よければ値と合わせて確認してみてください。インターフェース値の生成ついでに、itab構造体のfunフィールド(メソッドの配列)がどう生成されているか確認してみます。itab構造体の値はruntimeパッケージのtyp2Itab関数で生成されています(runtime/iface.go#L122)。tab}getitab関数でitab構造体の値を生成しているようなので、そちらもみてみます(runtime/iface.go#L22)。日本語のコメントは僕が挿入したものです。itab構造体のメモリ確保。m}メソッドへのポインタの配列は、二重forループのところで埋めています。コードの通りですが、インターフェースのメソッドと、インターフェースを実装した構造体のメソッドをマッチングし、マッチしたら配列にメソッドへのポインタを書き込みます。ちなみに省略しましたが、itab構造体はハッシュテーブルでキャッシュされています。インターフェース値を作成する度にマッチングをする必要はありません。Coxさんのブログ記事をかなり参考にしました。GDBで値を確認しつつGo言語のソースコードを読むと、Goの内部構造が少しみえてきて面白いです。ちなみに今回活躍したGDBですが、Go言語ではあまりうまく動かないと言われています。実際使っていても、stepコマンドを出したらGo内部の関数に飛んでしまったりしました。実アプリでデバッガを使いたい場合には、delve等のGo向けデバッガを使ったほうがよさそうです。Imageを格納できる。格納し...2016-12-23AppEngine/Goのテストに役立つライブラリluciの紹介こんばんは。2...2016-08-04GDBでGo言語のスライスの値をのぞいてみた最近Go言語をよく触っています。読者になる月別アーカイブはてなブログをはじめよう!ks888さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。