-analysis
フラグを付けて呼び出されると、godoc はインデックスを作成する Go パッケージに対して静的解析を実行し、その結果をソースビューとパッケージビューに表示します。このドキュメントでは、これらの機能の概要について説明します。
型解析機能
godoc -analysis=type
は、コンパイラが行うのと同様の静的チェックを実行します。不正な形式のプログラムを検出し、各識別子をそれが示すエンティティに解決し、各式の型と各型のメソッドセットを計算し、どの型が各インターフェース型に代入可能かを判断します。 **型解析** は比較的速く、例えば標準ライブラリの 200 以上のパッケージに対して約 10 秒かかります。
コンパイラエラー
ソースファイルにコンパイルエラーが含まれている場合、ソースビューはエラーのある場所を赤で強調表示します。マウスオーバーすると、エラーメッセージが表示されます。

識別子の解決
ソースビューでは、すべての参照識別子は、それが参照する言語エンティティ(パッケージ、定数、変数、型、関数、またはステートメントラベル)に関する情報で注釈が付けられます。識別子にマウスオーバーすると、エンティティの種類と型が表示されます(例:var x int
または func f func(int) string
)。


リンクをクリックすると、エンティティの定義に移動します。

型情報:サイズ/アライメント、メソッドセット、インターフェース
名前付き型を定義する識別子をクリックすると、パネルが表示され、名前付き型に関する情報(バイト単位のサイズとアライメント、メソッドセット、および*実装*関係:この型 U に代入可能または代入可能な型 T のセット。ここで、T または U の少なくとも一方はインターフェースです)が表示されます。この例は、net/rpc.methodType
に関する情報を示しています。

メソッドセットには、型の宣言されたメソッドだけでなく、この例の sync.Mutex
のように、構造体の匿名フィールドから「昇格」されたメソッドも含まれます。さらに、レシーバー型は、レシーバー値のアドレスが必要か、コピーだけが必要かによって、*T
または T
として表示されます。
メソッドセットと*実装*関係は、パッケージビューからも利用できます。

ポインタ解析機能
godoc -analysis=pointer
は、さらに正確なプログラム全体の **ポインタ解析** を実行します。言い換えれば、各参照(種類 *T
の変数だけでなく、[]T
、func
、map
、chan
、および interface
)が参照する可能性のあるメモリ位置のセットを近似します。この情報は、各動的呼び出しの可能な宛先(func
変数またはインターフェースメソッドを介して)、および同じチャネルでの送信操作と受信操作の関係を明らかにします。
型解析と比較して、ポインタ解析はより多くの時間とメモリを必要とし、100 万行を超えるコードベースには実用的ではありません。
コールグラフナビゲーション
ポインタ解析が完了すると、ソースビューはコードに **呼び出し元** と **呼び出し先** の情報を注釈として付けます。呼び出し元の情報は関数を宣言する func
キーワードに関連付けられ、呼び出し先の情報は関数呼び出しの開き括弧 '(
' に関連付けられます。
この例では、rot13
関数(strings/strings_test.go で定義)の宣言にマウスオーバーすると、それが正確に 1 か所で呼び出されていることがわかります。

リンクをクリックすると、唯一の呼び出し元に移動します。(複数の呼び出し元がある場合は、最初に選択肢のリストが表示されます。)

この呼び出しにマウスオーバーすると、このサイトで可能な呼び出し先が 19 個あり、そのうちの rot13
関数はそのうちの 1 つにすぎないことがわかります。これは、型 func(rune) rune
の変数を介した動的呼び出しです。呼び出しをクリックすると、切り詰められて表示されている、潜在的な呼び出し先 19 個すべてのリストが表示されます。それらの多くは匿名関数です。

ポインタ解析は、型ベースの手法と比較して、コールグラフの非常に正確な近似を提供します。その好例として、次の例は、ExampleXYZ
という名前のすべてのユーザー定義関数を呼び出す役割を担う testing
パッケージ内の動的呼び出しを示しています。

そのような関数はすべて型 func()
、つまり引数も結果もないことを思い出してください。型ベースの近似では、この呼び出しがその型に一致する任意の関数にディスパッチされる可能性があると結論付けることしかできません(そして、これらはほとんどのプログラムで非常に多数です)。しかし、ポインタ解析は、特定の func
値の testing
パッケージを通る流れを追跡できます。その精度を示すものとして、結果は名前が Example
で始まる関数のみを含んでいます。
パッケージ内コールグラフ
同じコールグラフ情報は、パッケージビューではまったく異なる方法で表示されます。各パッケージについて、インタラクティブなツリービューでは、そのパッケージに関連するコールグラフの探索が可能です。他のパッケージからのすべての関数は省略されます。ツリーのルートは、パッケージの外部エントリポイントです。エクスポートされた関数だけでなく、パッケージの外部から(動的に)呼び出される、エクスポートされていない関数または匿名関数も含まれます。
この例は、path/filepath
パッケージのエントリポイントを示しています。Glob
のコールグラフは数レベル展開されています

Glob と Join のノードが複数回表示されていることに注意してください。ツリーは循環グラフの部分的な展開です。完全な展開は一般に無限です。
パッケージビューにドキュメント化されている各関数について、別のインタラクティブなツリービューでは、その関数から始まる同じグラフの探索が可能です。これは、net/http.ListenAndServe
の内部グラフの一部です。

チャネルピア(送信 ↔ 受信)
並行 Go プログラムはチャネルを使用して値だけでなく異なるゴルーチン間の制御も渡すため、Go コードを読む際には、イベントのシーケンスを理解するためにチャネル送信から対応する受信に移動したいと思うのは当然です。
Godoc は、すべてのチャネル操作(make、send、range、receive、close)に、同じチャネルのエイリアスとなる可能性のある他の操作に関する情報を表示するパネルへのリンクを注釈として付けます。
この例は、net/http
のテストからのもので、chan bool
への送信操作を示しています。

<-
送信演算子をクリックすると、このチャネルが固有の場所(332 行目)で作られ、この値を読み取る可能性のある受信操作が 3 つあることがわかります。チャネル要素型の中には非常に広く使用されているもの(例:struct{}、bool、int、interface{})があり、典型的な Go プログラムには型 chan bool
の値に対する受信操作が数十個含まれている可能性があることは言うまでもありません。それでも、ポインタ解析は、型だけに基づくよりもはるかに細かい精度でチャネルの操作を区別できます。
また、送信は、make
操作と受信操作を含む外部の(匿名)関数とは異なる関数で発生することに注意してください。
これは、パッケージ net/http
における別の chan bool
への送信の別の例です

解析では、このチャネルから受信する可能性のある受信操作が 1 つだけ見つかりました。この機能のテストにあります。

既知の問題
すべての解析結果は、正確に 1 つの構成(例:amd64 linux)に関連しています。異なるプラットフォームまたはビルドタグに基づいて条件付きでコンパイルされるファイルは、解析では見えません。
import "C"
を使用するファイルは、cgo ツールによる前処理が必要です。 前処理後のファイルオフセットは、前処理されていないファイルと一致しないため、マークアップの位置がずれています。
ファイルは定期的に再解析されません。 実行中のサーバーの下でファイルが変更された場合、表示されるマークアップの位置がずれています。
その他の問題は、tools/godoc/analysis/README にリストされています。