[インデックス 12016] ファイルの概要
このコミットは、Go言語の標準ライブラリにおけるgo/ast
パッケージからgo/doc
パッケージへのExampleコード抽出ロジックの移動に関するものです。具体的には、GoのソースコードからExample関数(ExampleFoo
のような形式で記述され、_test.go
ファイルに配置されることが多い)を解析し、その情報を提供する機能がgo/ast
からgo/doc
へと移管されました。これにより、Exampleコードの処理がより適切なパッケージに集約され、go/doc
パッケージの責務が明確化されました。
コミット
commit b6e2d6b778aa63d10db72feb3b03fb0becac38da
Author: Robert Griesemer <gri@golang.org>
Date: Fri Feb 17 12:00:12 2012 -0800
go/doc: move Example code from go/ast to go/doc.
Fixes #3048.
R=rsc
CC=golang-dev
https://golang.org/cl/5672081
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/b6e2d6b778aa63d10db72feb3b03fb0becac38da
元コミット内容
このコミットの元の内容は、go/ast
パッケージに存在していたExampleコードを処理するロジックをgo/doc
パッケージに移動することです。これには、Example
構造体、Examples
関数、およびExampleの出力を解析する関連ヘルパー関数が含まれます。この移動に伴い、これらの機能を利用していたcmd/go
(Goコマンドラインツール)やcmd/godoc
(Goドキュメンテーションツール)などのコンシューマ側も、新しいgo/doc
パッケージのAPIを使用するように変更されています。
変更の背景
この変更の背景には、Go言語の標準ライブラリにおけるパッケージの責務の明確化があります。
- Issue #3048の解決: このコミットはGoのIssue #3048「
go/ast
should not know aboutExample
functions」を修正します。このIssueでは、go/ast
パッケージがExample関数に関する知識を持つべきではないという点が指摘されていました。go/ast
パッケージはGoのソースコードの抽象構文木(AST)を表現するためのものであり、特定のドキュメンテーションやテストの慣習(Example関数など)に関するロジックを持つことは、その責務を超えていると考えられました。 go/doc
の責務の強化:go/doc
パッケージは、Goのソースコードからドキュメンテーションを生成するための情報(パッケージ、型、関数、変数、定数、そしてExample)を抽出する役割を担っています。Example関数は、Goのドキュメンテーションシステムにおいて非常に重要な要素であり、コードの動作例を示すために使用されます。したがって、Exampleコードの解析と抽出のロジックは、ASTの構造そのものよりも、ドキュメンテーション生成の文脈でより適切にgo/doc
パッケージに属すると判断されました。- コードの分離と保守性の向上: Exampleコードの処理ロジックを
go/ast
からgo/doc
に移動することで、各パッケージの関心事が分離され、コードベース全体の保守性と理解度が向上します。go/ast
は純粋なAST表現に集中し、go/doc
はドキュメンテーション関連の処理に集中できるようになります。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念とツールに関する知識が必要です。
- Go言語のパッケージシステム: Goのコードはパッケージに分割され、再利用可能なモジュールとして機能します。各パッケージは特定の責務を持ちます。
go/ast
パッケージ: Goのソースコードを解析して生成される抽象構文木(Abstract Syntax Tree: AST)を表現するためのデータ構造と関数を提供します。プログラミング言語のコンパイラやツールがコードを理解・操作する際の基盤となります。go/doc
パッケージ: GoのソースコードからドキュメンテーションコメントやExample関数などの情報を抽出し、構造化されたドキュメンテーションデータを生成するための機能を提供します。godoc
ツールはこのパッケージを利用してドキュメンテーションを生成します。- GoのExample関数: Goでは、
func ExampleFoo()
やfunc ExamplePackage_Method()
のようにExample
プレフィックスを持つ関数を_test.go
ファイルに記述することで、コードの実行例を示すことができます。これらの関数はテストの一部として実行され、その出力が期待される出力と一致するか検証されます。また、godoc
ツールによって自動的にドキュメンテーションに組み込まれ、ユーザーがコードの動作を理解するのに役立ちます。 godoc
ツール: Go言語の公式ドキュメンテーションツールです。Goのソースコードからドキュメンテーションを抽出し、HTML形式で表示したり、コマンドラインで参照したりすることができます。Example関数もgodoc
によって表示されます。go test
コマンド: Goのテストを実行するためのコマンドです。Example関数もgo test
によって実行され、その出力が検証されます。src/cmd/dist/build.c
: GoのツールチェインをビルドするためのC言語のスクリプトです。Goの標準ライブラリパッケージのビルド順序やクリーンアップ対象などを定義しています。go.mod
/go.sum
: Goモジュールシステムにおける依存関係管理ファイルです。このコミットが行われた2012年時点ではGoモジュールは存在せず、Goのビルドシステムは異なる方法で依存関係を管理していました。しかし、概念としてはパッケージ間の依存関係を管理する仕組みが存在していました。
技術的詳細
このコミットの技術的詳細は、主に以下の点に集約されます。
- ファイルのリネームとパッケージ名の変更:
src/pkg/go/ast/example.go
がsrc/pkg/go/doc/example.go
にリネームされました。- これにより、ファイル内のパッケージ宣言が
package ast
からpackage doc
に変更されました。
- 型定義の移動と修飾:
go/ast
パッケージに存在していたExample
構造体(Example関数のメタデータを保持)がgo/doc
パッケージに移動しました。Example
構造体内のフィールド(Code
,Comments
)や、Examples
関数、exampleOutput
関数が引数として受け取る型(File
,GenDecl
,FuncDecl
,CommentGroup
)は、元々go/ast
パッケージ内で定義されていました。これらがgo/doc
パッケージに移動したことで、これらの型を参照する際にはast.Node
,ast.CommentGroup
,ast.File
,ast.GenDecl
,ast.FuncDecl
のように明示的にast
パッケージを修飾する必要が生じました。
- 依存関係の更新:
src/pkg/go/doc/example.go
(旧src/pkg/go/ast/example.go
)は、go/ast
パッケージの型を使用するため、新たにimport "go/ast"
が追加されました。src/cmd/go/test.go
とsrc/cmd/godoc/godoc.go
は、Example関数を処理するためにgo/ast.Examples
ではなくgo/doc.Examples
を使用するように変更されました。これに伴い、これらのファイルでもimport "go/doc"
が追加されています。src/cmd/dist/build.c
では、ビルド順序とクリーンアップ対象にpkg/go/doc
が追加されました。これは、go/doc
パッケージがGoのビルドシステムにおいて重要なコンポーネントとして認識され、適切にビルドおよび管理される必要があることを示しています。
- APIの変更:
ast.Examples
関数は削除され、代わりにdoc.Examples
関数が提供されるようになりました。この関数は、*ast.File
のスライスを受け取り、*doc.Example
のスライスを返します。godoc
ツール内のexample_htmlFunc
関数やPageInfo
構造体、getPageInfo
関数など、Example情報を扱う部分の型シグネチャが*ast.Example
から*doc.Example
に変更されました。
この変更は、Goのツールチェイン内部のアーキテクチャを改善し、各コンポーネントの責務をより明確にするための重要なステップでした。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。
-
src/pkg/go/{ast => doc}/example.go
(ファイルのリネームと内容変更):src/pkg/go/ast/example.go
からsrc/pkg/go/doc/example.go
へのファイル名変更。- パッケージ宣言が
package ast
からpackage doc
へ変更。 import "go/ast"
の追加。Example
構造体内のCode
、Comments
フィールドの型がNode
、*CommentGroup
からast.Node
、*ast.CommentGroup
へ変更。Examples
関数の引数files ...*File
がfiles ...*ast.File
へ変更。- 関数内部で参照される
GenDecl
、FuncDecl
、CommentGroup
などの型がast.GenDecl
、ast.FuncDecl
、ast.CommentGroup
へ変更。
-
src/cmd/go/test.go
:import "go/doc"
の追加。ast.Examples(f)
の呼び出しがdoc.Examples(f)
へ変更。
-
src/cmd/godoc/godoc.go
:example_htmlFunc
関数の引数examples []*ast.Example
がexamples []*doc.Example
へ変更。PageInfo
構造体のExamples []*ast.Example
がExamples []*doc.Example
へ変更。getPageInfo
関数内でexamples []*ast.Example
の宣言がexamples []*doc.Example
へ変更。ast.Examples(files...)
の呼び出しがdoc.Examples(files...)
へ変更。
-
src/cmd/dist/build.c
:buildorder
配列に"pkg/go/doc"
を追加。cleantab
配列に"pkg/go/doc"
を追加。
コアとなるコードの解説
src/pkg/go/{ast => doc}/example.go
の変更
このファイルは、Example関数を解析し、その構造を表現するExample
型と、ファイルからExampleを抽出するExamples
関数を定義しています。
変更前 (package ast
):
package ast
type Example struct {
Name string // name of the item being exemplified
Doc string // example function doc string
Code Node
Comments []*CommentGroup
Output string // expected output
}
func Examples(files ...*File) []*Example { ... }
Code
やComments
の型、Examples
関数の引数*File
は、同じast
パッケージ内で定義されている型を参照していました。
変更後 (package doc
):
package doc
import (
"go/ast" // astパッケージをインポート
"go/token"
"regexp"
"sort"
)
type Example struct {
Name string // name of the item being exemplified
Doc string // example function doc string
Code ast.Node // ast.Nodeに明示的に変更
Comments []*ast.CommentGroup // ast.CommentGroupに明示的に変更
Output string // expected output
}
func Examples(files ...*ast.File) []*Example { // 引数もast.Fileに明示的に変更
var list []*Example
for _, file := range files {
// ...
if g, ok := decl.(*ast.GenDecl); ok && g.Tok != token.IMPORT { // ast.GenDeclに明示的に変更
// ...
}
f, ok := decl.(*ast.FuncDecl) // ast.FuncDeclに明示的に変更
if !ok {
continue
}
// ...
}
// ...
}
func exampleOutput(fun *ast.FuncDecl, comments []*ast.CommentGroup) string { // ast.FuncDecl, ast.CommentGroupに明示的に変更
// ...
var last *ast.CommentGroup // ast.CommentGroupに明示的に変更
// ...
}
この変更により、Example
構造体やExamples
関数はgo/doc
パッケージの一部となりました。しかし、Example関数の解析には依然としてASTの構造(ast.Node
, ast.File
, ast.FuncDecl
など)が必要なため、go/ast
パッケージをインポートし、これらの型をast.
で修飾して使用するようになりました。これは、Exampleの抽出ロジックがASTの知識に依存しつつも、そのロジック自体はドキュメンテーション生成の責務を持つgo/doc
に属するという、より適切な分離を示しています。
src/cmd/go/test.go
と src/cmd/godoc/godoc.go
の変更
これらのファイルは、Example関数を実際に利用するツール(go test
とgodoc
)のコードです。
変更前:
// src/cmd/go/test.go
import (
// ...
"go/ast"
// ...
)
// ...
for _, e := range ast.Examples(f) { // astパッケージのExamples関数を呼び出し
// ...
}
// src/cmd/godoc/godoc.go
import (
// ...
"go/ast"
// ...
)
// ...
func example_htmlFunc(funcName string, examples []*ast.Example, fset *token.FileSet) string { // ast.Example型を使用
// ...
}
// ...
examples = append(examples, ast.Examples(files...)...) // astパッケージのExamples関数を呼び出し
変更後:
// src/cmd/go/test.go
import (
// ...
"go/ast"
"go/doc" // docパッケージをインポート
// ...
)
// ...
for _, e := range doc.Examples(f) { // docパッケージのExamples関数を呼び出し
// ...
}
// src/cmd/godoc/godoc.go
import (
// ...
"go/ast"
"go/doc" // docパッケージをインポート
// ...
)
// ...
func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.FileSet) string { // doc.Example型を使用
// ...
}
// ...
examples = append(examples, doc.Examples(files...)...) // docパッケージのExamples関数を呼び出し
これらの変更は、Exampleコードの抽出ロジックがgo/ast
からgo/doc
へ移動したことに伴う、API利用箇所の更新です。これにより、go test
やgodoc
は、Exampleに関する情報を取得する際に、より高レベルな抽象化を提供するgo/doc
パッケージを利用するようになりました。
src/cmd/dist/build.c
の変更
このファイルはGoのビルドシステムの一部であり、Goの標準ライブラリパッケージのビルド順序やクリーンアップ対象を定義しています。
変更前: go/doc
は明示的にリストされていませんでした。
変更後:
static char *buildorder[] = {
// ...
"pkg/text/template",
"pkg/go/doc", // 追加
"cmd/go",
};
static char *cleantab[] = {
// ...
"pkg/go/build",
"pkg/go/doc", // 追加
"pkg/go/parser",
// ...
};
pkg/go/doc
がbuildorder
とcleantab
に追加されたことで、go/doc
パッケージがGoのビルドプロセスにおいて正式なビルド対象およびクリーンアップ対象として認識されるようになりました。これは、go/doc
がExampleコードの処理という重要な機能を担うようになったため、そのビルドと管理が適切に行われる必要があることを示しています。
関連リンク
- Go Issue #3048: https://github.com/golang/go/issues/3048
- Go Change-ID 5672081: https://golang.org/cl/5672081 (Gerritの変更履歴)
- Go言語の
go/ast
パッケージドキュメンテーション (現在のもの): https://pkg.go.dev/go/ast - Go言語の
go/doc
パッケージドキュメンテーション (現在のもの): https://pkg.go.dev/go/doc - Go言語のExample関数に関する公式ブログ記事 (Go 1.0リリース時のもの): https://go.dev/blog/go1.0 (Example関数に関する記述が含まれる可能性があります)
参考にした情報源リンク
- Go Issue #3048の議論内容
- Go言語の公式ドキュメンテーション(
go/ast
およびgo/doc
パッケージ) - Go言語のソースコード(コミット前後の差分)
- Go言語のExample関数に関する一般的な知識
godoc
ツールの機能に関する知識go test
コマンドの機能に関する知識- Go言語のビルドシステムに関する一般的な知識
- Go言語の歴史と進化に関する情報