[インデックス 12209] ファイルの概要
このコミットは、Go言語の標準ライブラリである go/ast
パッケージに、ast.Print
および ast.Inspect
関数の使用例を示すテストファイル src/pkg/go/ast/example_test.go
を追加するものです。これにより、Goプログラムの抽象構文木(AST)を操作・検査する方法が具体的に示され、開発者がこれらの機能を理解しやすくなります。
コミット
commit 34e60a81d5b9a3c18d634d89acea9384605f4916
Author: Robert Griesemer <gri@golang.org>
Date: Fri Feb 24 13:44:36 2012 -0800
go/ast: examples for ast.Print, ast.Inspect
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5700057
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/34e60a81d5b9a3c18d634d89acea9384605f4916
元コミット内容
go/ast: examples for ast.Print, ast.Inspect
このコミットは、go/ast
パッケージの ast.Print
関数と ast.Inspect
関数の使用例を追加します。
変更の背景
Go言語の go/ast
パッケージは、Goプログラムのソースコードを解析して抽象構文木(AST)を構築し、そのASTを操作するための機能を提供します。しかし、これらの強力な機能は、特に初心者にとっては直感的に理解しにくい場合があります。ast.Print
はASTをデバッグ目的で整形して出力するのに役立ち、ast.Inspect
はASTを走査して特定のノードを検査するのに使用されます。
このコミットの背景には、これらの重要な関数の使い方を明確に示し、開発者がGoのツールや静的解析ツールを構築する際に go/ast
パッケージをより効果的に活用できるようにするという意図があります。具体的な使用例を提供することで、学習曲線が緩和され、パッケージの採用が促進されます。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念と標準ライブラリの知識が必要です。
-
抽象構文木 (Abstract Syntax Tree, AST): ASTは、プログラミング言語のソースコードの抽象的な構文構造を木構造で表現したものです。各ノードはソースコードの構成要素(変数、関数、式、文など)を表し、その子ノードはそれらの構成要素の内部構造を示します。コンパイラやリンター、コードフォーマッターなどのツールは、ソースコードをASTに変換し、そのASTを操作することで様々な処理を行います。
-
go/parser
パッケージ:go/parser
パッケージは、Go言語のソースコードを解析し、そのASTを生成するための機能を提供します。parser.ParseFile
関数は、指定されたファイルまたは文字列からGoのソースコードを読み込み、*ast.File
型のASTルートノードを返します。 -
go/token
パッケージ:go/token
パッケージは、Goソースコード内の位置情報(ファイル名、行番号、列番号など)を管理するための型と関数を提供します。token.FileSet
は、複数のファイルにわたる位置情報を一元的に管理するために使用されます。ASTノードは、ソースコード内の対応する位置への参照をtoken.Pos
型で保持します。 -
go/ast
パッケージ:go/ast
パッケージは、GoプログラムのASTを表現する型(ast.Node
インターフェースとその実装型)と、ASTを操作するためのユーティリティ関数を提供します。ast.Node
: AST内のすべてのノードが実装するインターフェースです。ast.Print(fset *token.FileSet, x interface{})
: ASTの構造をデバッグ目的で整形して標準出力に表示する関数です。fset
は位置情報を解決するために使用され、x
は表示したいASTノード(通常は*ast.File
)です。ast.Inspect(node ast.Node, f func(ast.Node) bool)
: ASTを深さ優先で走査(トラバース)するための関数です。引数f
は、各ノードが訪問されるたびに呼び出されるコールバック関数です。このコールバック関数がfalse
を返すと、そのノードの子孫の走査は停止します。これにより、特定の種類のノードを検索したり、ASTの特定の部分を処理したりすることができます。
-
Goのテストにおける
Example
関数: Goのテストフレームワークでは、Example
関数という特別な形式のテスト関数をサポートしています。これらの関数は、コードの実行例を示すために使用され、その出力はコメントとして// output:
の後に記述されます。go test
コマンドは、この出力コメントと実際の実行結果を比較し、一致しない場合はテスト失敗とします。これにより、コードのドキュメントとテストを同時に行うことができ、例が常に最新かつ正確であることを保証できます。
技術的詳細
このコミットは、src/pkg/go/ast/example_test.go
という新しいファイルを追加することで、go/ast
パッケージの ast.Inspect
と ast.Print
関数の具体的な使用方法をデモンストレーションしています。
ExampleInspect()
関数
ExampleInspect()
関数は、GoプログラムのASTを検査する方法を示しています。
-
ソースコードの準備:
src
変数に、検査対象となるGoのソースコード(package p; const c = 1.0; var X = f(3.14)*2 + c;
)が文字列リテラルとして定義されています。 -
ASTの生成:
token.NewFileSet()
で新しいFileSet
が作成され、parser.ParseFile(fset, "src.go", src, 0)
を使用して、このソースコードからASTが生成されます。parser.ParseFile
は、ソースコードを解析し、その結果として*ast.File
型のASTルートノードを返します。 -
ASTの検査 (
ast.Inspect
):ast.Inspect(f, func(n ast.Node) bool { ... })
が呼び出され、生成されたASTf
が走査されます。無名関数が各ASTノードn
に対して呼び出されます。- この無名関数内では、
switch x := n.(type)
を使用して、現在のノードn
の具体的な型をチェックしています。 - もしノードが
*ast.BasicLit
(基本的なリテラル、例:1.0
,2
,3.14
)または*ast.Ident
(識別子、例:p
,c
,X
,f
)であれば、その値または名前が抽出されます。 - 抽出された値は、
fset.Position(n.Pos())
を使ってソースコード内の正確な位置情報(ファイル名、行番号、列番号)と共にfmt.Printf
で出力されます。 - コールバック関数は常に
true
を返すため、ASTのすべてのノードが再帰的に走査されます。
- この無名関数内では、
-
期待される出力:
// output:
コメントブロックには、この例を実行した際に期待される出力が記述されており、go test
コマンドによって検証されます。出力は、ソースコード内の各識別子とリテラルの位置と値を示しています。
ExamplePrint()
関数
ExamplePrint()
関数は、デバッグ目的でASTを整形して出力する方法を示しています。
-
ソースコードの準備:
src
変数に、ASTとして出力したいGoのソースコード(package main; func main() { println("Hello, World!") }
)が定義されています。 -
ASTの生成:
token.NewFileSet()
とparser.ParseFile(fset, "", src, 0)
を使用して、このソースコードからASTが生成されます。 -
ASTの出力 (
ast.Print
):ast.Print(fset, f)
が呼び出され、生成されたASTf
がFileSet
fset
を使って整形され、標準出力に詳細な構造として出力されます。この出力は、ASTの各ノードの型、フィールド、値、そしてソースコード内の位置情報(行番号と列番号)を階層的に示します。 -
期待される出力:
// output:
コメントブロックには、ast.Print
によって生成されるASTの構造が詳細に記述されています。これは、ASTの内部構造を理解し、デバッグする上で非常に役立ちます。
これらの例は、go/ast
パッケージが提供するAST操作の基本的なパターンを明確に示しており、Goの静的解析やコード生成ツール開発の出発点として機能します。
コアとなるコードの変更箇所
このコミットによって追加されたファイルは src/pkg/go/ast/example_test.go
です。
--- /dev/null
+++ b/src/pkg/go/ast/example_test.go
@@ -0,0 +1,136 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ast_test
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+)
+
+// This example demonstrates how to inspect the AST of a Go program.
+func ExampleInspect() {
+ // src is the input for which we want to inspect the AST.
+ src := `
+package p
+const c = 1.0
+var X = f(3.14)*2 + c
+`
+
+ // Create the AST by parsing src.
+ fset := token.NewFileSet() // positions are relative to fset
+ f, err := parser.ParseFile(fset, "src.go", src, 0)
+ if err != nil {
+ panic(err)
+ }
+
+ // Inspect the AST and print all identifiers and literals.
+ ast.Inspect(f, func(n ast.Node) bool {
+ var s string
+ switch x := n.(type) {
+ case *ast.BasicLit:
+ s = x.Value
+ case *ast.Ident:
+ s = x.Name
+ }
+ if s != "" {
+ fmt.Printf("%s:\t%s\n", fset.Position(n.Pos()), s)
+ }
+ return true
+ })
+
+ // output:
+ // src.go:2:9: p
+ // src.go:3:7: c
+ // src.go:3:11: 1.0
+ // src.go:4:5: X
+ // src.go:4:9: f
+ // src.go:4:11: 3.14
+ // src.go:4:17: 2
+ // src.go:4:21: c
+}
+
+// This example shows what an AST looks like when printed for debugging.
+func ExamplePrint() {
+ // src is the input for which we want to print the AST.
+ src := `
+package main
+func main() {
+ println("Hello, World!")
+}
+`
+
+ // Create the AST by parsing src.
+ fset := token.NewFileSet() // positions are relative to fset
+ f, err := parser.ParseFile(fset, "", src, 0)
+ if err != nil {
+ panic(err)
+ }
+
+ // Print the AST.
+ ast.Print(fset, f)
+
+ // output:
+ // 0 *ast.File {
+ // 1 . Package: 2:1
+ // 2 . Name: *ast.Ident {
+ // 3 . . NamePos: 2:9
+ // 4 . . Name: "main"
+ // 5 . }
+ // 6 . Decls: []ast.Decl (len = 1) {
+ // 7 . . 0: *ast.FuncDecl {
+ // 8 . . . Name: *ast.Ident {
+ // 9 . . . . NamePos: 3:6
+ // 10 . . . . Name: "main"
+ // 11 . . . . Obj: *ast.Object {
+ // 12 . . . . . Kind: func
+ // 13 . . . . . Name: "main"
+ // 14 . . . . . Decl: *(obj @ 7)
+ // 15 . . . . }
+ // 16 . . . }
+ // 17 . . . Type: *ast.FuncType {
+ // 18 . . . . Func: 3:1
+ // 19 . . . . Params: *ast.FieldList {
+ // 20 . . . . . Opening: 3:10
+ // 21 . . . . . Closing: 3:11
+ // 22 . . . . }
+ // 23 . . . }
+ // 24 . . . Body: *ast.BlockStmt {
+ // 25 . . . . Lbrace: 3:13
+ // 26 . . . . List: []ast.Stmt (len = 1) {
+ // 27 . . . . . 0: *ast.ExprStmt {
+ // 28 . . . . . . X: *ast.CallExpr {
+ // 29 . . . . . . . Fun: *ast.Ident {
+ // 30 . . . . . . . . NamePos: 4:2
+ // 31 . . . . . . . . Name: "println"
+ // 32 . . . . . . . }
+ // 33 . . . . . . . Lparen: 4:9
+ // 34 . . . . . . . Args: []ast.Expr (len = 1) {
+ // 35 . . . . . . . . 0: *ast.BasicLit {
+ // 36 . . . . . . . . . ValuePos: 4:10
+ // 37 . . . . . . . . . Kind: STRING
+ // 38 . . . . . . . . . Value: "\"Hello, World!\""\n
+ // 39 . . . . . . . . }\n
+ // 40 . . . . . . . }\n
+ // 41 . . . . . . . Ellipsis: -\n
+ // 42 . . . . . . . Rparen: 4:25\n
+ // 43 . . . . . . }\n
+ // 44 . . . . . }\n
+ // 45 . . . . }\n
+ // 46 . . . . Rbrace: 5:1\n
+ // 47 . . . }\n
+ // 48 . . }\n
+ // 49 . }\n
+ // 50 . Scope: *ast.Scope {\n
+ // 51 . . Objects: map[string]*ast.Object (len = 1) {\n
+ // 52 . . . "main": *(obj @ 11)\n+ // 53 . . }\n+ // 54 . }\n+ // 55 . Unresolved: []*ast.Ident (len = 1) {\n+ // 56 . . 0: *(obj @ 29)\n+ // 57 . }\n+ // 58 }\n+}
コアとなるコードの解説
追加された example_test.go
ファイルは、go/ast
パッケージの機能を実演するための2つの Example
関数を含んでいます。
-
ExampleInspect()
: この関数は、ast.Inspect
を使用してGoコードのASTを走査し、特定のノード(識別子と基本的なリテラル)を抽出してその位置と値を出力する方法を示しています。parser.ParseFile
でソースコードからASTを生成します。ast.Inspect
のコールバック関数内で、型アサーションn.(type)
を使ってノードの型を*ast.BasicLit
または*ast.Ident
に絞り込みます。fset.Position(n.Pos())
を使って、ノードがソースコードのどの位置にあるかを正確に取得し、出力に含めます。- これにより、Goコード内の個々の要素がAST上でどのように表現され、どのようにアクセスできるかが視覚的に理解できます。
-
ExamplePrint()
: この関数は、ast.Print
を使用してGoコードのASTをデバッグ目的で整形して出力する方法を示しています。- 同様に
parser.ParseFile
でASTを生成します。 ast.Print(fset, f)
を呼び出すだけで、ASTの完全な階層構造と各ノードの詳細情報(型、フィールド、値、ソースコード上の位置)が標準出力に表示されます。- この出力は、ASTの内部構造を深く理解したい場合や、特定のASTノードが期待通りに構築されているかを確認したい場合に非常に有用です。
- 同様に
これらの例は、go/ast
パッケージの基本的なAPIを効果的に使用するための実践的なガイドラインを提供し、Goの静的解析ツールやコード生成ツールを開発する際の出発点となります。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/
go/ast
パッケージのドキュメント: https://pkg.go.dev/go/astgo/parser
パッケージのドキュメント: https://pkg.go.dev/go/parsergo/token
パッケージのドキュメント: https://pkg.go.dev/go/token- このコミットのGo Gerritレビューページ: https://golang.org/cl/5700057
参考にした情報源リンク
- Go言語の公式ドキュメント (
go/ast
,go/parser
,go/token
パッケージ) - Go言語のテストに関するドキュメント (Example関数について)
- 抽象構文木 (AST) に関する一般的な情報
- Go Gerrit Code Review (コミットメッセージ内の
golang.org/cl
リンク)
[インデックス 12209] ファイルの概要
このコミットは、Go言語の標準ライブラリである go/ast
パッケージに、ast.Print
および ast.Inspect
関数の使用例を示すテストファイル src/pkg/go/ast/example_test.go
を追加するものです。これにより、Goプログラムの抽象構文木(AST)を操作・検査する方法が具体的に示され、開発者がこれらの機能を理解しやすくなります。
コミット
commit 34e60a81d5b9a3c18d634d89acea9384605f4916
Author: Robert Griesemer <gri@golang.org>
Date: Fri Feb 24 13:44:36 2012 -0800
go/ast: examples for ast.Print, ast.Inspect
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5700057
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/34e60a81d5b9a3c18d634d89acea9384605f4916
元コミット内容
go/ast: examples for ast.Print, ast.Inspect
このコミットは、go/ast
パッケージの ast.Print
関数と ast.Inspect
関数の使用例を追加します。
変更の背景
Go言語の go/ast
パッケージは、Goプログラムのソースコードを解析して抽象構文木(AST)を構築し、そのASTを操作するための機能を提供します。しかし、これらの強力な機能は、特に初心者にとっては直感的に理解しにくい場合があります。ast.Print
はASTをデバッグ目的で整形して出力するのに役立ち、ast.Inspect
はASTを走査して特定のノードを検査するのに使用されます。
このコミットの背景には、これらの重要な関数の使い方を明確に示し、開発者がGoのツールや静的解析ツールを構築する際に go/ast
パッケージをより効果的に活用できるようにするという意図があります。具体的な使用例を提供することで、学習曲線が緩和され、パッケージの採用が促進されます。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念と標準ライブラリの知識が必要です。
-
抽象構文木 (Abstract Syntax Tree, AST): ASTは、プログラミング言語のソースコードの抽象的な構文構造を木構造で表現したものです。各ノードはソースコードの構成要素(変数、関数、式、文など)を表し、その子ノードはそれらの構成要素の内部構造を示します。コンパイラやリンター、コードフォーマッターなどのツールは、ソースコードをASTに変換し、そのASTを操作することで様々な処理を行います。
-
go/parser
パッケージ:go/parser
パッケージは、Go言語のソースコードを解析し、そのASTを生成するための機能を提供します。parser.ParseFile
関数は、指定されたファイルまたは文字列からGoのソースコードを読み込み、*ast.File
型のASTルートノードを返します。 -
go/token
パッケージ:go/token
パッケージは、Goソースコード内の位置情報(ファイル名、行番号、列番号など)を管理するための型と関数を提供します。token.FileSet
は、複数のファイルにわたる位置情報を一元的に管理するために使用されます。ASTノードは、ソースコード内の対応する位置への参照をtoken.Pos
型で保持します。 -
go/ast
パッケージ:go/ast
パッケージは、GoプログラムのASTを表現する型(ast.Node
インターフェースとその実装型)と、ASTを操作するためのユーティリティ関数を提供します。ast.Node
: AST内のすべてのノードが実装するインターフェースです。ast.Print(fset *token.FileSet, x interface{})
: ASTの構造をデバッグ目的で整形して標準出力に表示する関数です。fset
は位置情報を解決するために使用され、x
は表示したいASTノード(通常は*ast.File
)です。ast.Inspect(node ast.Node, f func(ast.Node) bool)
: ASTを深さ優先で走査(トラバース)するための関数です。引数f
は、各ノードが訪問されるたびに呼び出されるコールバック関数です。このコールバック関数がfalse
を返すと、そのノードの子孫の走査は停止します。これにより、特定の種類のノードを検索したり、ASTの特定の部分を処理したりすることができます。
-
Goのテストにおける
Example
関数: Goのテストフレームワークでは、Example
関数という特別な形式のテスト関数をサポートしています。これらの関数は、コードの実行例を示すために使用され、その出力はコメントとして// output:
の後に記述されます。go test
コマンドは、この出力コメントと実際の実行結果を比較し、一致しない場合はテスト失敗とします。これにより、コードのドキュメントとテストを同時に行うことができ、例が常に最新かつ正確であることを保証できます。
技術的詳細
このコミットは、src/pkg/go/ast/example_test.go
という新しいファイルを追加することで、go/ast
パッケージの ast.Inspect
と ast.Print
関数の具体的な使用方法をデモンストレーションしています。
ExampleInspect()
関数
ExampleInspect()
関数は、GoプログラムのASTを検査する方法を示しています。
-
ソースコードの準備:
src
変数に、検査対象となるGoのソースコード(package p; const c = 1.0; var X = f(3.14)*2 + c;
)が文字列リテラルとして定義されています。 -
ASTの生成:
token.NewFileSet()
で新しいFileSet
が作成され、parser.ParseFile(fset, "src.go", src, 0)
を使用して、このソースコードからASTが生成されます。parser.ParseFile
は、ソースコードを解析し、その結果として*ast.File
型のASTルートノードを返します。 -
ASTの検査 (
ast.Inspect
):ast.Inspect(f, func(n ast.Node) bool { ... })
が呼び出され、生成されたASTf
が走査されます。無名関数が各ASTノードn
に対して呼び出されます。- この無名関数内では、
switch x := n.(type)
を使用して、現在のノードn
の具体的な型をチェックしています。 - もしノードが
*ast.BasicLit
(基本的なリテラル、例:1.0
,2
,3.14
)または*ast.Ident
(識別子、例:p
,c
,X
,f
)であれば、その値または名前が抽出されます。 - 抽出された値は、
fset.Position(n.Pos())
を使ってソースコード内の正確な位置情報(ファイル名、行番号、列番号)と共にfmt.Printf
で出力されます。 - コールバック関数は常に
true
を返すため、ASTのすべてのノードが再帰的に走査されます。
- この無名関数内では、
-
期待される出力:
// output:
コメントブロックには、この例を実行した際に期待される出力が記述されており、go test
コマンドによって検証されます。出力は、ソースコード内の各識別子とリテラルの位置と値を示しています。
ExamplePrint()
関数
ExamplePrint()
関数は、デバッグ目的でASTを整形して出力する方法を示しています。
-
ソースコードの準備:
src
変数に、ASTとして出力したいGoのソースコード(package main; func main() { println("Hello, World!") }
)が定義されています。 -
ASTの生成:
token.NewFileSet()
とparser.ParseFile(fset, "", src, 0)
を使用して、このソースコードからASTが生成されます。 -
ASTの出力 (
ast.Print
):ast.Print(fset, f)
が呼び出され、生成されたASTf
がFileSet
fset
を使って整形され、標準出力に詳細な構造として出力されます。この出力は、ASTの各ノードの型、フィールド、値、そしてソースコード内の位置情報(行番号と列番号)を階層的に示します。 -
期待される出力:
// output:
コメントブロックには、ast.Print
によって生成されるASTの構造が詳細に記述されています。これは、ASTの内部構造を理解し、デバッグする上で非常に役立ちます。
これらの例は、go/ast
パッケージが提供するAST操作の基本的なパターンを明確に示しており、Goの静的解析やコード生成ツール開発の出発点として機能します。
コアとなるコードの変更箇所
このコミットによって追加されたファイルは src/pkg/go/ast/example_test.go
です。
--- /dev/null
+++ b/src/pkg/go/ast/example_test.go
@@ -0,0 +1,136 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ast_test
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+)
+
+// This example demonstrates how to inspect the AST of a Go program.
+func ExampleInspect() {
+ // src is the input for which we want to inspect the AST.
+ src := `
+package p
+const c = 1.0
+var X = f(3.14)*2 + c
+`
+
+ // Create the AST by parsing src.
+ fset := token.NewFileSet() // positions are relative to fset
+ f, err := parser.ParseFile(fset, "src.go", src, 0)
+ if err != nil {
+ panic(err)
+ }
+
+ // Inspect the AST and print all identifiers and literals.
+ ast.Inspect(f, func(n ast.Node) bool {
+ var s string
+ switch x := n.(type) {
+ case *ast.BasicLit:
+ s = x.Value
+ case *ast.Ident:
+ s = x.Name
+ }
+ if s != "" {
+ fmt.Printf("%s:\t%s\n", fset.Position(n.Pos()), s)
+ }
+ return true
+ })
+
+ // output:
+ // src.go:2:9: p
+ // src.go:3:7: c
+ // src.go:3:11: 1.0
+ // src.go:4:5: X
+ // src.go:4:9: f
+ // src.go:4:11: 3.14
+ // src.go:4:17: 2
+ // src.go:4:21: c
+}
+
+// This example shows what an AST looks like when printed for debugging.
+func ExamplePrint() {
+ // src is the input for which we want to print the AST.
+ src := `
+package main
+func main() {
+ println("Hello, World!")
+}
+`
+
+ // Create the AST by parsing src.
+ fset := token.NewFileSet() // positions are relative to fset
+ f, err := parser.ParseFile(fset, "", src, 0)
+ if err != nil {
+ panic(err)
+ }
+
+ // Print the AST.
+ ast.Print(fset, f)
+
+ // output:
+ // 0 *ast.File {
+ // 1 . Package: 2:1
+ // 2 . Name: *ast.Ident {
+ // 3 . . NamePos: 2:9
+ // 4 . . Name: "main"
+ // 5 . }
+ // 6 . Decls: []ast.Decl (len = 1) {
+ // 7 . . 0: *ast.FuncDecl {
+ // 8 . . . Name: *ast.Ident {
+ // 9 . . . . NamePos: 3:6
+ // 10 . . . . Name: "main"
+ // 11 . . . . Obj: *ast.Object {
+ // 12 . . . . . Kind: func
+ // 13 . . . . . Name: "main"
+ // 14 . . . . . Decl: *(obj @ 7)
+ // 15 . . . . }
+ // 16 . . . }
+ // 17 . . . Type: *ast.FuncType {
+ // 18 . . . . Func: 3:1
+ // 19 . . . . Params: *ast.FieldList {
+ // 20 . . . . . Opening: 3:10
+ // 21 . . . . . Closing: 3:11
+ // 22 . . . . }
+ // 23 . . . }
+ // 24 . . . Body: *ast.BlockStmt {
+ // 25 . . . . Lbrace: 3:13
+ // 26 . . . . List: []ast.Stmt (len = 1) {
+ // 27 . . . . . 0: *ast.ExprStmt {
+ // 28 . . . . . . X: *ast.CallExpr {
+ // 29 . . . . . . . Fun: *ast.Ident {
+ // 30 . . . . . . . . NamePos: 4:2
+ // 31 . . . . . . . . Name: "println"
+ // 32 . . . . . . . }
+ // 33 . . . . . . . Lparen: 4:9
+ // 34 . . . . . . . Args: []ast.Expr (len = 1) {
+ // 35 . . . . . . . . 0: *ast.BasicLit {
+ // 36 . . . . . . . . . ValuePos: 4:10
+ // 37 . . . . . . . . . Kind: STRING
+ // 38 . . . . . . . . . Value: "\"Hello, World!\""\n
+ // 39 . . . . . . . . }\n
+ // 40 . . . . . . . }\n
+ // 41 . . . . . . . Ellipsis: -\n
+ // 42 . . . . . . . Rparen: 4:25\n
+ // 43 . . . . . . }\n
+ // 44 . . . . . }\n
+ // 45 . . . . }\n
+ // 46 . . . . Rbrace: 5:1\n
+ // 47 . . . }\n
+ // 48 . . }\n
+ // 49 . }\n
+ // 50 . Scope: *ast.Scope {\n
+ // 51 . . Objects: map[string]*ast.Object (len = 1) {\n
+ // 52 . . . "main": *(obj @ 11)\n+ // 53 . . }\n+ // 54 . }\n+ // 55 . Unresolved: []*ast.Ident (len = 1) {\n+ // 56 . . 0: *(obj @ 29)\n+ // 57 . }\n+ // 58 }\n+}
コアとなるコードの解説
追加された example_test.go
ファイルは、go/ast
パッケージの機能を実演するための2つの Example
関数を含んでいます。
-
ExampleInspect()
: この関数は、ast.Inspect
を使用してGoコードのASTを走査し、特定のノード(識別子と基本的なリテラル)を抽出してその位置と値を出力する方法を示しています。parser.ParseFile
でソースコードからASTを生成します。ast.Inspect
のコールバック関数内で、型アサーションn.(type)
を使ってノードの型を*ast.BasicLit
または*ast.Ident
に絞り込みます。fset.Position(n.Pos())
を使って、ノードがソースコードのどの位置にあるかを正確に取得し、出力に含めます。- これにより、Goコード内の個々の要素がAST上でどのように表現され、どのようにアクセスできるかが視覚的に理解できます。
-
ExamplePrint()
: この関数は、ast.Print
を使用してGoコードのASTをデバッグ目的で整形して出力する方法を示しています。- 同様に
parser.ParseFile
でASTを生成します。 ast.Print(fset, f)
を呼び出すだけで、ASTの完全な階層構造と各ノードの詳細情報(型、フィールド、値、ソースコード上の位置)が標準出力に表示されます。- この出力は、ASTの内部構造を深く理解したい場合や、特定のASTノードが期待通りに構築されているかを確認したい場合に非常に有用です。
- 同様に
これらの例は、go/ast
パッケージの基本的なAPIを効果的に使用するための実践的なガイドラインを提供し、Goの静的解析ツールやコード生成ツールを開発する際の出発点となります。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/
go/ast
パッケージのドキュメント: https://pkg.go.dev/go/astgo/parser
パッケージのドキュメント: https://pkg.go.dev/go/parsergo/token
パッケージのドキュメント: https://pkg.go.dev/go/token- このコミットのGo Gerritレビューページ: https://golang.org/cl/5700057
参考にした情報源リンク
- Go言語の公式ドキュメント (
go/ast
,go/parser
,go/token
パッケージ) - Go言語のテストに関するドキュメント (Example関数について)
- 抽象構文木 (AST) に関する一般的な情報
- Go Gerrit Code Review (コミットメッセージ内の
golang.org/cl
リンク)