Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 19070] ファイルの概要

このコミットは、go list -f コマンドのテンプレート機能に、ビルドコンテキスト情報 (go/build.Context の値) を利用できるようにする変更を導入しています。これにより、ユーザーは go list -f の出力テンプレート内で、ターゲットアーキテクチャ (GOARCH) やビルドタグ (BuildTags) といったビルド環境に関する情報にアクセスできるようになります。

コミット

  • コミットハッシュ: b3a33a654d2f640f3b6c7856ea742c23f6c49d1c
  • Author: Rick Arnold rickarnoldjr@gmail.com
  • Date: Tue Apr 8 22:35:29 2014 -0400

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/b3a33a654d2f640f3b6c7856ea742c23f6c49d1c

元コミット内容

cmd/go: allow use of Context in 'go list -f'

Add a $Context variable to the template so that the build.Context values
such as BuildTags can be accessed.

Fixes #6666.

LGTM=adg, rsc
R=golang-codereviews, gobot, adg, rsc
CC=golang-codereviews
https://golang.org/cl/72770043

変更の背景

go list コマンドは、Goパッケージに関する情報を表示するための強力なツールです。特に -f フラグを使用すると、Goの text/template パッケージの構文を用いて、出力形式を自由にカスタマイズできます。しかし、これまでの go list -f のテンプレートでは、各パッケージのメタデータ(インポートパス、ディレクトリ、ファイルリストなど)にはアクセスできましたが、Goのビルド環境に関する情報(例えば、現在のターゲットOSやアーキテクチャ、有効なビルドタグなど)には直接アクセスできませんでした。

この制限は、特定のビルド環境に依存する情報を go list の出力に含めたい場合に問題となります。例えば、特定のビルドタグが有効な場合にのみ表示されるパッケージを識別したり、異なるOSやアーキテクチャ向けにビルドされた場合のパッケージの挙動をシミュレートしたりする際に、ビルドコンテキスト情報へのアクセスが必要となります。

このコミットは、このギャップを埋めるために、go list -f のテンプレート内で build.Context の値にアクセスできる $Context 変数を導入しました。これにより、ユーザーはより柔軟で情報豊富な go list の出力を生成できるようになります。コミットメッセージにある Fixes #6666 は、この機能追加の必要性を示唆する既存の課題があったことを意味しています。

前提知識の解説

go list コマンドと -f フラグ

go list は、Goのワークスペース内のパッケージに関する情報を表示するコマンドです。例えば、go list all はすべてのパッケージのインポートパスを表示します。 -f フラグは、出力形式をカスタマイズするために使用されます。このフラグに続く文字列は、Goの text/template パッケージの構文として解釈されます。テンプレートには、各パッケージの Package 構造体の情報が渡されます。

例: go list -f '{{.ImportPath}} {{.Dir}}' は、各パッケージのインポートパスとディレクトリを表示します。

Goの text/template パッケージ

text/template パッケージは、Go言語に組み込まれているテキストテンプレートエンジンです。プレースホルダー({{.Field}})や制御構造({{if .Condition}}...{{end}}{{range .Slice}}...{{end}})を使用して、動的にテキストを生成できます。また、カスタム関数を登録してテンプレート内で利用することも可能です。

go/build.Context 構造体

go/build パッケージは、Goのビルドプロセスに関する情報を提供します。その中の Context 構造体は、Goのビルド環境に関する様々な設定をカプセル化しています。これには以下のようなフィールドが含まれます。

  • GOARCH: ターゲットアーキテクチャ (例: amd64, arm)
  • GOOS: ターゲットオペレーティングシステム (例: linux, windows, darwin)
  • GOROOT: Goのインストールルートディレクトリ
  • GOPATH: Goのワークスペースパス
  • CgoEnabled: cgoが有効かどうか
  • BuildTags: ビルド制約 (+build ディレクティブ) にマッチするビルドタグのリスト
  • ReleaseTags: 現在のリリースと互換性のあるリリースを示すタグのリスト

これらの情報は、Goがソースファイルをどのようにコンパイルし、どのファイルを含めるかを決定する際に使用されます。

技術的詳細

このコミットの主要な目的は、go list -f のテンプレート内で go/build.Context の情報にアクセスできるようにすることです。これを実現するために、以下の技術的な変更が加えられました。

  1. Context 構造体の定義と newContext 関数の追加 (src/cmd/go/context.go): cmd/go パッケージ内に、go/build.Context の主要なフィールドをミラーリングする新しい Context 構造体が定義されました。この構造体は、JSONシリアライズ可能 (json:",omitempty") に設定されており、将来的に go list -json の出力にも含めることができるように設計されています。 また、go/build.Context のインスタンスを受け取り、新しく定義された Context 構造体のインスタンスを生成する newContext ヘルパー関数が追加されました。これにより、go/build パッケージのコンテキスト情報を、テンプレートが利用できる形式に変換します。

  2. テンプレート関数 context の追加 (src/cmd/go/list.go): go list コマンドのテンプレート処理ロジック (runList 関数) が変更され、新しいテンプレート関数 contexttemplate.FuncMap に追加されました。この context 関数は、go/build パッケージのグローバルなビルドコンテキスト (buildContext) をラップした Context 構造体のインスタンスを返します。このインスタンスは一度生成されるとキャッシュされ、テンプレート内で複数回 context 関数が呼び出されても同じインスタンスが返されるように最適化されています。

  3. ドキュメントの更新 (src/cmd/go/doc.go): go list -f のドキュメントが更新され、新しく追加された context テンプレート関数とその戻り値である Context 構造体について説明が追加されました。これにより、ユーザーは新しい機能の存在と使い方を理解できます。

  4. テストケースの追加 (src/cmd/go/test.bash): 新しい機能が正しく動作することを確認するために、go list -f "GOARCH: {{context.GOARCH}}" を実行し、期待される出力が得られるかを検証するテストケースが test.bash スクリプトに追加されました。これは、go list がビルドコンテキスト情報にアクセスできることを保証します。

これらの変更により、go list -f のテンプレート内で {{context.GOARCH}}{{context.BuildTags}} のようにビルドコンテキストのフィールドに直接アクセスできるようになり、go list の機能が大幅に拡張されました。

コアとなるコードの変更箇所

src/cmd/go/context.go (新規ファイル)

// Copyright 2014 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 main

import (
	"go/build"
)

type Context struct {
	GOARCH        string   `json:",omitempty"` // target architecture
	GOOS          string   `json:",omitempty"` // target operating system
	GOROOT        string   `json:",omitempty"` // Go root
	GOPATH        string   `json:",omitempty"` // Go path
	CgoEnabled    bool     `json:",omitempty"` // whether cgo can be used
	UseAllFiles   bool     `json:",omitempty"` // use files regardless of +build lines, file names
	Compiler      string   `json:",omitempty"` // compiler to assume when computing target paths
	BuildTags     []string `json:",omitempty"` // build constraints to match in +build lines
	ReleaseTags   []string `json:",omitempty"` // releases the current release is compatible with
	InstallSuffix string   `json:",omitempty"` // suffix to use in the name of the install dir
}

func newContext(c *build.Context) *Context {
	return &Context{
		GOARCH:        c.GOARCH,
		GOOS:          c.GOOS,
		GOROOT:        c.GOROOT,
		CgoEnabled:    c.CgoEnabled,
		UseAllFiles:   c.UseAllFiles,
		Compiler:      c.Compiler,
		BuildTags:     c.BuildTags,
		ReleaseTags:   c.ReleaseTags,
		InstallSuffix: c.InstallSuffix,
	}
}

src/cmd/go/doc.go (変更箇所)

--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -283,8 +283,7 @@ The default output shows the package import path:
 
 The -f flag specifies an alternate format for the list, using the
 syntax of package template.  The default output is equivalent to -f
-`{{.ImportPath}}`.  One extra template function is available, "join",
-which calls strings.Join. The struct being passed to the template is:
+`{{.ImportPath}}`. The struct being passed to the template is:
 
      type Package struct {
          Dir        string // directory containing package sources
@@ -332,6 +331,26 @@ which calls strings.Join. The struct being passed to the template is:
          XTestImports []string // imports from XTestGoFiles
      }
 
+The template function "join" calls strings.Join.
+
+The template function "context" returns the build context, defined as:
+
+	type Context struct {
+		GOARCH        string   // target architecture
+		GOOS          string   // target operating system
+		GOROOT        string   // Go root
+		GOPATH        string   // Go path
+		CgoEnabled    bool     // whether cgo can be used
+		UseAllFiles   bool     // use files regardless of +build lines, file names
+		Compiler      string   // compiler to assume when computing target paths
+		BuildTags     []string // build constraints to match in +build lines
+		ReleaseTags   []string // releases the current release is compatible with
+		InstallSuffix string   // suffix to use in the name of the install dir
+	}
+
+For more information about the meaning of these fields see the documentation
+for the go/build package's Context type.
+
 The -json flag causes the package data to be printed in JSON format
 instead of using the template format.

src/cmd/go/list.go (変更箇所)

--- a/src/cmd/go/list.go
+++ b/src/cmd/go/list.go
@@ -27,8 +27,7 @@ The default output shows the package import path:
 
 The -f flag specifies an alternate format for the list, using the
 syntax of package template.  The default output is equivalent to -f
-`{{.ImportPath}}`.  One extra template function is available, "join",
-which calls strings.Join. The struct being passed to the template is:
+`{{.ImportPath}}`. The struct being passed to the template is:
 
      type Package struct {
          Dir        string // directory containing package sources
@@ -76,6 +75,26 @@ which calls strings.Join. The struct being passed to the template is:
          XTestImports []string // imports from XTestGoFiles
      }
 
+The template function "join" calls strings.Join.
+
+The template function "context" returns the build context, defined as:
+
+	type Context struct {
+		GOARCH        string   // target architecture
+		GOOS          string   // target operating system
+		GOROOT        string   // Go root
+		GOPATH        string   // Go path
+		CgoEnabled    bool     // whether cgo can be used
+		UseAllFiles   bool     // use files regardless of +build lines, file names
+		Compiler      string   // compiler to assume when computing target paths
+		BuildTags     []string // build constraints to match in +build lines
+		ReleaseTags   []string // releases the current release is compatible with
+		InstallSuffix string   // suffix to use in the name of the install dir
+	}
+
+For more information about the meaning of these fields see the documentation
+for the go/build package's Context type.
+
 The -json flag causes the package data to be printed in JSON format
 instead of using the template format.
 
@@ -131,7 +150,18 @@ func runList(cmd *Command, args []string) {
 		`out.Write(nl)`
 		}
 	} else {
-		`tmpl, err := template.New("main").Funcs(template.FuncMap{"join": strings.Join}).Parse(*listFmt)`
+		`var cachedCtxt *Context`
+		`context := func() *Context {`
+		`	if cachedCtxt == nil {`
+		`		cachedCtxt = newContext(&buildContext)`
+		`	}`
+		`	return cachedCtxt`
+		`}`
+		`fm := template.FuncMap{`
+		`	"join":    strings.Join,`
+		`	"context": context,`
+		`}`
+		`tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)`
 		`if err != nil {`
 		`	fatalf("%s", err)`
 		`}`

src/cmd/go/test.bash (変更箇所)

--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -694,6 +694,12 @@ unset go_cmds
 unset ldflags
 unset GOPATH
 
+TEST list template can use context function
+if ! ./testgo list -f "GOARCH: {{context.GOARCH}}"; then 
+	echo unable to use context in list template
+	ok=false
+fi
+
 # clean up
 if $started; then stop; fi
 rm -rf testdata/bin testdata/bin1

コアとなるコードの解説

src/cmd/go/context.go

このファイルは、go list -f テンプレートに公開される Context 型を定義しています。この型は go/build.Context のサブセットであり、ビルド環境に関する重要な情報(GOARCH, GOOS, BuildTags など)を保持します。newContext 関数は、実際の go/build.Context インスタンスからこの Context 型のインスタンスを生成するファクトリ関数として機能します。json:",omitempty" タグは、この構造体がJSONとしてシリアライズされる際に、値が空の場合にフィールドを省略することを示しています。

src/cmd/go/doc.go

この変更は、go list -f コマンドのヘルプドキュメントを更新しています。特に、context という新しいテンプレート関数が利用可能になったことと、その関数が返す Context 構造体の定義が追加されています。これにより、ユーザーは go list -f でビルドコンテキスト情報にアクセスする方法を公式ドキュメントで確認できるようになります。

src/cmd/go/list.go

このファイルは go list コマンドの主要なロジックを含んでいます。変更の核心は runList 関数内にあります。 以前は template.FuncMapjoin 関数のみが登録されていましたが、このコミットにより context 関数も追加されました。 context 関数はクロージャとして定義されており、cachedCtxt という変数を使って Context インスタンスをキャッシュします。これにより、テンプレート内で context 関数が複数回呼び出されても、newContext が一度だけ実行され、パフォーマンスが向上します。 buildContextgo/build パッケージのグローバルなビルドコンテキスト変数であり、現在のGo環境のビルド設定を保持しています。

src/cmd/go/test.bash

このシェルスクリプトは、Goコマンドの統合テストを実行します。追加されたテストケースは、go list -f "GOARCH: {{context.GOARCH}}" を実行し、その出力が期待通りであるかを確認します。これは、context テンプレート関数が正しく機能し、GOARCH の値がテンプレートに渡されることを検証するものです。このテストの成功は、新機能が意図通りに動作していることの保証となります。

関連リンク

参考にした情報源リンク

  • Go Command Documentation: go help list (Goの go list コマンドに関する公式ドキュメント)
  • text/template package documentation: https://pkg.go.dev/text/template (Goのテキストテンプレートパッケージに関する公式ドキュメント)
  • go/build package documentation: https://pkg.go.dev/go/build (Goのビルドパッケージに関する公式ドキュメント)
  • Web search for "go list -f template context"
  • Web search for "go/build.Context struct fields"
I have generated the detailed explanation in Markdown format, following all the specified instructions and including all the required sections. I have used the commit data and the web search results to provide comprehensive explanations for each section.
I will now output this to standard output.# [インデックス 19070] ファイルの概要

このコミットは、`go list -f` コマンドのテンプレート機能に、ビルドコンテキスト情報 (`go/build.Context` の値) を利用できるようにする変更を導入しています。これにより、ユーザーは `go list -f` の出力テンプレート内で、ターゲットアーキテクチャ (`GOARCH`) やビルドタグ (`BuildTags`) といったビルド環境に関する情報にアクセスできるようになります。

## コミット

- **コミットハッシュ**: `b3a33a654d2f640f3b6c7856ea742c23f6c49d1c`
- **Author**: Rick Arnold <rickarnoldjr@gmail.com>
- **Date**: Tue Apr 8 22:35:29 2014 -0400

## GitHub上でのコミットページへのリンク

[https://github.com/golang/go/commit/b3a33a654d2f640f3b6c7856ea742c23f6c49d1c](https://github.com/golang.com/go/commit/b3a33a654d2f640f3b6c7856ea742c23f6c49d1c)

## 元コミット内容

cmd/go: allow use of Context in 'go list -f'

Add a $Context variable to the template so that the build.Context values such as BuildTags can be accessed.

Fixes #6666.

LGTM=adg, rsc R=golang-codereviews, gobot, adg, rsc CC=golang-codereviews https://golang.org/cl/72770043


## 変更の背景

`go list` コマンドは、Goパッケージに関する情報を表示するための強力なツールです。特に `-f` フラグを使用すると、Goの `text/template` パッケージの構文を用いて、出力形式を自由にカスタマイズできます。しかし、これまでの `go list -f` のテンプレートでは、各パッケージのメタデータ(インポートパス、ディレクトリ、ファイルリストなど)にはアクセスできましたが、Goのビルド環境に関する情報(例えば、現在のターゲットOSやアーキテクチャ、有効なビルドタグなど)には直接アクセスできませんでした。

この制限は、特定のビルド環境に依存する情報を `go list` の出力に含めたい場合に問題となります。例えば、特定のビルドタグが有効な場合にのみ表示されるパッケージを識別したり、異なるOSやアーキテクチャ向けにビルドされた場合のパッケージの挙動をシミュレートしたりする際に、ビルドコンテキスト情報へのアクセスが必要となります。

このコミットは、このギャップを埋めるために、`go list -f` のテンプレート内で `build.Context` の値にアクセスできる `$Context` 変数を導入しました。これにより、ユーザーはより柔軟で情報豊富な `go list` の出力を生成できるようになります。コミットメッセージにある `Fixes #6666` は、この機能追加の必要性を示唆する既存の課題があったことを意味しています。

## 前提知識の解説

### `go list` コマンドと `-f` フラグ

`go list` は、Goのワークスペース内のパッケージに関する情報を表示するコマンドです。例えば、`go list all` はすべてのパッケージのインポートパスを表示します。
`-f` フラグは、出力形式をカスタマイズするために使用されます。このフラグに続く文字列は、Goの `text/template` パッケージの構文として解釈されます。テンプレートには、各パッケージの `Package` 構造体の情報が渡されます。

例: `go list -f '{{.ImportPath}} {{.Dir}}'` は、各パッケージのインポートパスとディレクトリを表示します。

### Goの `text/template` パッケージ

`text/template` パッケージは、Go言語に組み込まれているテキストテンプレートエンジンです。プレースホルダー(`{{.Field}}`)や制御構造(`{{if .Condition}}...{{end}}`、`{{range .Slice}}...{{end}}`)を使用して、動的にテキストを生成できます。また、カスタム関数を登録してテンプレート内で利用することも可能です。

### `go/build.Context` 構造体

`go/build` パッケージは、Goのビルドプロセスに関する情報を提供します。その中の `Context` 構造体は、Goのビルド環境に関する様々な設定をカプセル化しています。これには以下のようなフィールドが含まれます。

*   `GOARCH`: ターゲットアーキテクチャ (例: `amd64`, `arm`)
*   `GOOS`: ターゲットオペレーティングシステム (例: `linux`, `windows`, `darwin`)
*   `GOROOT`: Goのインストールルートディレクトリ
*   `GOPATH`: Goのワークスペースパス
*   `CgoEnabled`: cgoが有効かどうか
*   `BuildTags`: ビルド制約 (`+build` ディレクティブ) にマッチするビルドタグのリスト
*   `ReleaseTags`: 現在のリリースと互換性のあるリリースを示すタグのリスト

これらの情報は、Goがソースファイルをどのようにコンパイルし、どのファイルを含めるかを決定する際に使用されます。

## 技術的詳細

このコミットの主要な目的は、`go list -f` のテンプレート内で `go/build.Context` の情報にアクセスできるようにすることです。これを実現するために、以下の技術的な変更が加えられました。

1.  **`Context` 構造体の定義と `newContext` 関数の追加 (`src/cmd/go/context.go`)**:
    `cmd/go` パッケージ内に、`go/build.Context` の主要なフィールドをミラーリングする新しい `Context` 構造体が定義されました。この構造体は、JSONシリアライズ可能 (`json:",omitempty"`) に設定されており、将来的に `go list -json` の出力にも含めることができるように設計されています。
    また、`go/build.Context` のインスタンスを受け取り、新しく定義された `Context` 構造体のインスタンスを生成する `newContext` ヘルパー関数が追加されました。これにより、`go/build` パッケージのコンテキスト情報を、テンプレートが利用できる形式に変換します。

2.  **テンプレート関数 `context` の追加 (`src/cmd/go/list.go`)**:
    `go list` コマンドのテンプレート処理ロジック (`runList` 関数) が変更され、新しいテンプレート関数 `context` が `template.FuncMap` に追加されました。この `context` 関数は、`go/build` パッケージのグローバルなビルドコンテキスト (`buildContext`) をラップした `Context` 構造体のインスタンスを返します。このインスタンスは一度生成されるとキャッシュされ、テンプレート内で複数回 `context` 関数が呼び出されても同じインスタンスが返されるように最適化されています。

3.  **ドキュメントの更新 (`src/cmd/go/doc.go`)**:
    `go list -f` のドキュメントが更新され、新しく追加された `context` テンプレート関数とその戻り値である `Context` 構造体について説明が追加されました。これにより、ユーザーは新しい機能の存在と使い方を理解できます。

4.  **テストケースの追加 (`src/cmd/go/test.bash`)**:
    新しい機能が正しく動作することを確認するために、`go list -f "GOARCH: {{context.GOARCH}}"` を実行し、期待される出力が得られるかを検証するテストケースが `test.bash` スクリプトに追加されました。これは、`go list` がビルドコンテキスト情報にアクセスできることを保証します。

これらの変更により、`go list -f` のテンプレート内で `{{context.GOARCH}}` や `{{context.BuildTags}}` のようにビルドコンテキストのフィールドに直接アクセスできるようになり、`go list` の機能が大幅に拡張されました。

## コアとなるコードの変更箇所

### `src/cmd/go/context.go` (新規ファイル)

```go
// Copyright 2014 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 main

import (
	"go/build"
)

type Context struct {
	GOARCH        string   `json:",omitempty"` // target architecture
	GOOS          string   `json:",omitempty"` // target operating system
	GOROOT        string   `json:",omitempty"` // Go root
	GOPATH        string   `json:",omitempty"` // Go path
	CgoEnabled    bool     `json:",omitempty"` // whether cgo can be used
	UseAllFiles   bool     `json:",omitempty"` // use files regardless of +build lines, file names
	Compiler      string   `json:",omitempty"` // compiler to assume when computing target paths
	BuildTags     []string `json:",omitempty"` // build constraints to match in +build lines
	ReleaseTags   []string `json:",omitempty"` // releases the current release is compatible with
	InstallSuffix string   `json:",omitempty"` // suffix to use in the name of the install dir
}

func newContext(c *build.Context) *Context {
	return &Context{
		GOARCH:        c.GOARCH,
		GOOS:          c.GOOS,
		GOROOT:        c.GOROOT,
		CgoEnabled:    c.CgoEnabled,
		UseAllFiles:   c.UseAllFiles,
		Compiler:      c.Compiler,
		BuildTags:     c.BuildTags,
		ReleaseTags:   c.ReleaseTags,
		InstallSuffix: c.InstallSuffix,
	}
}

src/cmd/go/doc.go (変更箇所)

--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -283,8 +283,7 @@ The default output shows the package import path:
 
 The -f flag specifies an alternate format for the list, using the
 syntax of package template.  The default output is equivalent to -f
-`{{.ImportPath}}`.  One extra template function is available, "join",
-which calls strings.Join. The struct being passed to the template is:
+`{{.ImportPath}}`. The struct being passed to the template is:
 
      type Package struct {
          Dir        string // directory containing package sources
@@ -332,6 +331,26 @@ which calls strings.Join. The struct being passed to the template is:
          XTestImports []string // imports from XTestGoFiles
      }
 
+The template function "join" calls strings.Join.
+
+The template function "context" returns the build context, defined as:
+
+	type Context struct {
+		GOARCH        string   // target architecture
+		GOOS          string   // target operating system
+		GOROOT        string   // Go root
+		GOPATH        string   // Go path
+		CgoEnabled    bool     // whether cgo can be used
+		UseAllFiles   bool     // use files regardless of +build lines, file names
+		Compiler      string   // compiler to assume when computing target paths
+		BuildTags     []string // build constraints to match in +build lines
+		ReleaseTags   []string // releases the current release is compatible with
+		InstallSuffix string   // suffix to use in the name of the install dir
+	}
+
+For more information about the meaning of these fields see the documentation
+for the go/build package's Context type.
+
 The -json flag causes the package data to be printed in JSON format
 instead of using the template format.

src/cmd/go/list.go (変更箇所)

--- a/src/cmd/go/list.go
+++ b/src/cmd/go/list.go
@@ -27,8 +27,7 @@ The default output shows the package import path:
 
 The -f flag specifies an alternate format for the list, using the
 syntax of package template.  The default output is equivalent to -f
-`{{.ImportPath}}`.  One extra template function is available, "join",
-which calls strings.Join. The struct being passed to the template is:
+`{{.ImportPath}}`. The struct being passed to the template is:
 
      type Package struct {
          Dir        string // directory containing package sources
@@ -76,6 +75,26 @@ which calls strings.Join. The struct being passed to the template is:
          XTestImports []string // imports from XTestGoFiles
      }
 
+The template function "join" calls strings.Join.
+
+The template function "context" returns the build context, defined as:
+
+	type Context struct {
+		GOARCH        string   // target architecture
+		GOOS          string   // target operating system
+		GOROOT        string   // Go root
+		GOPATH        string   // Go path
+		CgoEnabled    bool     // whether cgo can be used
+		UseAllFiles   bool     // use files regardless of +build lines, file names
+		Compiler      string   // compiler to assume when computing target paths
+		BuildTags     []string // build constraints to match in +build lines
+		ReleaseTags   []string // releases the current release is compatible with
+		InstallSuffix string   // suffix to use in the name of the install dir
+	}
+
+For more information about the meaning of these fields see the documentation
+for the go/build package's Context type.
+
 The -json flag causes the package data to be printed in JSON format
 instead of using the template format.
 
@@ -131,7 +150,18 @@ func runList(cmd *Command, args []string) {
 		`out.Write(nl)`
 		}
 	} else {
-		`tmpl, err := template.New("main").Funcs(template.FuncMap{"join": strings.Join}).Parse(*listFmt)`
+		`var cachedCtxt *Context`
+		`context := func() *Context {`
+		`	if cachedCtxt == nil {`
+		`		cachedCtxt = newContext(&buildContext)`
+		`	}`
+		`	return cachedCtxt`
+		`}`
+		`fm := template.FuncMap{`
+		`	"join":    strings.Join,`
+		`	"context": context,`
+		`}`
+		`tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)`
 		`if err != nil {`
 		`	fatalf("%s", err)`
 		`}`

src/cmd/go/test.bash (変更箇所)

--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -694,6 +694,12 @@ unset go_cmds
 unset ldflags
 unset GOPATH
 
+TEST list template can use context function
+if ! ./testgo list -f "GOARCH: {{context.GOARCH}}"; then 
+	echo unable to use context in list template
+	ok=false
+fi
+
 # clean up
 if $started; then stop; fi
 rm -rf testdata/bin testdata/bin1

コアとなるコードの解説

src/cmd/go/context.go

このファイルは、go list -f テンプレートに公開される Context 型を定義しています。この型は go/build.Context のサブセットであり、ビルド環境に関する重要な情報(GOARCH, GOOS, BuildTags など)を保持します。newContext 関数は、実際の go/build.Context インスタンスからこの Context 型のインスタンスを生成するファクトリ関数として機能します。json:",omitempty" タグは、この構造体がJSONとしてシリアライズされる際に、値が空の場合にフィールドを省略することを示しています。

src/cmd/go/doc.go

この変更は、go list -f コマンドのヘルプドキュメントを更新しています。特に、context という新しいテンプレート関数が利用可能になったことと、その関数が返す Context 構造体の定義が追加されています。これにより、ユーザーは go list -f でビルドコンテキスト情報にアクセスする方法を公式ドキュメントで確認できるようになります。

src/cmd/go/list.go

このファイルは go list コマンドの主要なロジックを含んでいます。変更の核心は runList 関数内にあります。 以前は template.FuncMapjoin 関数のみが登録されていましたが、このコミットにより context 関数も追加されました。 context 関数はクロージャとして定義されており、cachedCtxt という変数を使って Context インスタンスをキャッシュします。これにより、テンプレート内で context 関数が複数回呼び出されても、newContext が一度だけ実行され、パフォーマンスが向上します。 buildContextgo/build パッケージのグローバルなビルドコンテキスト変数であり、現在のGo環境のビルド設定を保持しています。

src/cmd/go/test.bash

このシェルスクリプトは、Goコマンドの統合テストを実行します。追加されたテストケースは、go list -f "GOARCH: {{context.GOARCH}}" を実行し、その出力が期待通りであるかを確認します。これは、context テンプレート関数が正しく機能し、GOARCH の値がテンプレートに渡されることを検証するものです。このテストの成功は、新機能が意図通りに動作していることの保証となります。

関連リンク

参考にした情報源リンク

  • Go Command Documentation: go help list (Goの go list コマンドに関する公式ドキュメント)
  • text/template package documentation: https://pkg.go.dev/text/template (Goのテキストテンプレートパッケージに関する公式ドキュメント)
  • go/build package documentation: https://pkg.go.dev/go/build (Goのビルドパッケージに関する公式ドキュメント)
  • Web search for "go list -f template context"
  • Web search for "go/build.Context struct fields"