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

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

このコミットは、Go言語のビルドシステムにおいて、go/build パッケージに go1.2 ビルドタグを追加するものです。これにより、Go 1.2リリース以降のGoバージョンでコンパイルされるコードが、特定のGoバージョンに依存するコードブロックを条件付きで含めることができるようになります。これは、Go言語のリリース管理と後方互換性を維持するための重要なメカニズムの一部です。

コミット

commit 3861cb438857d3cb55c1465d2d8d37621db01e93
Author: Péter Surányi <speter.go1@gmail.com>
Date:   Mon Sep 23 18:11:25 2013 +1000

    go/build: add go1.2 build tag
    
    Fixes #6449.
    
    R=golang-dev, adg
    CC=golang-dev
    https://golang.org/cl/13829044
---
 src/pkg/go/build/build.go | 2 +-|
 1 file changed, 1 insertion(+), 1 deletion(-)|

diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index d608f0410e..8b6b2636ae 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -295,7 +295,7 @@ func defaultContext() Context {
  	// When we reach Go 1.3 the line will read
  	//	c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"}
  	// and so on.
- 	c.ReleaseTags = []string{"go1.1"}
+ 	c.ReleaseTags = []string{"go1.1", "go1.2"}
  
  	switch os.Getenv("CGO_ENABLED") {
  	case "1":

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

https://github.com/golang/go/commit/3861cb438857d3cb55c1465d2d8d37621db01e93

元コミット内容

go/build: add go1.2 build tag

Fixes #6449.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/13829044

変更の背景

この変更の背景には、Go言語のバージョン管理と、特定のGoバージョンに特化したコードのコンパイルを可能にするビルドタグの仕組みがあります。Go言語は定期的に新しいバージョンをリリースし、それぞれのバージョンで新機能の追加や既存機能の改善が行われます。しかし、開発者が特定のGoバージョンでのみ利用可能な機能を使用したい場合や、異なるGoバージョン間でコードの振る舞いを変更したい場合があります。

go/build パッケージは、Goのソースコードを解析し、ビルドプロセスを制御する役割を担っています。このパッケージは、Goのツールチェイン(go build, go run など)によって利用され、どのファイルをコンパイルに含めるかを決定します。

Go 1.2のリリースが近づくにつれて、Go 1.2で導入される新機能や変更に対応するために、go1.2 というビルドタグが必要になりました。このタグを追加することで、開発者は以下のようなディレクティブをソースファイルに記述できるようになります。

// +build go1.2

package mypackage

// Go 1.2以降でのみコンパイルされるコード

これにより、Go 1.2以降のコンパイラでビルドされた場合にのみ、このコードブロックが有効になります。これは、Goの異なるバージョン間での互換性を維持しつつ、新しいバージョン固有の機能を利用するための重要なメカニズムです。コミットメッセージにある Fixes #6449 は、この変更がGoのIssue 6449を解決することを示しており、このIssueが go1.2 ビルドタグの必要性に関する議論や要望であったことを示唆しています。

前提知識の解説

Goビルドタグ (Build Tags)

Goのビルドタグは、Goソースファイルの先頭に記述される特別なコメント行で、特定の条件に基づいてファイルのコンパイルを制御するために使用されます。これらのタグは、// +build tagname の形式で記述され、複数のタグをスペースで区切って指定することも、カンマで区切って論理OR条件として指定することも可能です。

例:

  • // +build linux darwin: LinuxまたはmacOSでのみコンパイル
  • // +build !windows: Windows以外でコンパイル
  • // +build debug: debug タグが有効な場合のみコンパイル

Goのビルドツールは、コンパイル時に有効なビルドタグを決定し、それに基づいてどのソースファイルをビルドに含めるかを判断します。これにより、プラットフォーム固有のコード、デバッグ用のコード、または特定のGoバージョンに依存するコードなどを、条件付きでコンパイルすることができます。

go/build パッケージ

go/build パッケージは、Goのソースコードパッケージの構造を理解し、ビルドプロセスをサポートするための機能を提供します。このパッケージは、Goの標準ライブラリの一部であり、go buildgo install といったコマンドの内部で利用されています。

go/build パッケージの主要な機能には以下のようなものがあります。

  • パッケージの検索: 指定されたパスやインポートパスに基づいてGoパッケージを検索します。
  • ソースファイルの解析: Goソースファイルを解析し、パッケージ名、インポート、ビルドタグなどの情報を抽出します。
  • ビルドコンテキストの管理: ビルド環境(OS、アーキテクチャ、Goバージョンなど)に関する情報を含む Context オブジェクトを提供します。この Context オブジェクトには、有効なビルドタグのリストも含まれます。
  • 依存関係の解決: パッケージ間の依存関係を解決し、ビルド順序を決定します。

このコミットで変更されている c.ReleaseTags は、go/build パッケージの Context 構造体の一部であり、Goのリリースバージョンに対応するビルドタグのリストを保持しています。

Goのリリース管理と後方互換性

Go言語は、厳格な後方互換性ポリシーを持っています。これは、新しいGoバージョンがリリースされても、既存のGoプログラムが引き続き動作することを保証するというものです。しかし、時には言語や標準ライブラリに破壊的な変更を加える必要がある場合もあります。このような場合、ビルドタグは、異なるGoバージョン間でコードの振る舞いを調整するための手段として機能します。

go1.x という形式のビルドタグは、特定のGoバージョン以降で利用可能な機能や変更に対応するために使用されます。例えば、go1.2 タグは、Go 1.2で導入された機能を利用するコードを、それ以前のGoバージョンでコンパイルされないようにするために使用されます。これにより、開発者は新しいGoバージョンの恩恵を受けつつ、古いGoバージョンとの互換性を維持することができます。

技術的詳細

このコミットの技術的な核心は、src/pkg/go/build/build.go ファイル内の defaultContext() 関数における c.ReleaseTags スライスの更新です。

defaultContext() 関数は、Goのビルドツールが使用するデフォルトのビルドコンテキストを初期化する役割を担っています。このコンテキストには、現在のオペレーティングシステム、アーキテクチャ、そしてGoのリリースバージョンに対応するビルドタグのリストが含まれます。

変更前のコードでは、c.ReleaseTags[]string{"go1.1"} と初期化されていました。これは、Go 1.1がリリースされた時点でのデフォルトのビルドタグを示しています。コメントにもあるように、Go 1.3がリリースされる際には {"go1.1", "go1.2", "go1.3"} のようになることが意図されていました。

このコミットでは、Go 1.2のリリースに備えて、c.ReleaseTags"go1.2" が追加され、[]string{"go1.1", "go1.2"} となりました。

この変更がもたらす影響は以下の通りです。

  1. go1.2 ビルドタグの認識: Go 1.2以降のビルドツールは、// +build go1.2 というディレクティブを持つソースファイルを正しく認識し、コンパイル対象に含めることができるようになります。これにより、開発者はGo 1.2で導入された新機能やAPIを利用するコードを、それ以前のGoバージョンと区別して記述できるようになります。
  2. 後方互換性の維持: 例えば、Go 1.2で非推奨になった機能や、振る舞いが変更された機能がある場合、開発者は // +build !go1.2 のようなタグを使用して、Go 1.2以前のバージョンでのみ有効なコードパスを維持することができます。
  3. 条件付きコンパイルの強化: この変更により、Goのビルドシステムは、よりきめ細やかな条件付きコンパイルをサポートできるようになります。これは、クロスプラットフォーム開発や、異なるGoバージョン間でのコードの移植性を高める上で非常に重要です。
  4. Goリリースサイクルの反映: c.ReleaseTags の更新は、Go言語のリリースサイクルと密接に連携しています。新しいメジャーバージョンがリリースされるたびに、対応するビルドタグがこのリストに追加され、Goのツールチェインがそのバージョンを認識できるように準備されます。

この変更は、Goのビルドシステムの中核部分に位置するため、Go言語の進化と、開発者が異なるGoバージョン間でコードを管理する方法に直接的な影響を与えます。

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

--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -295,7 +295,7 @@ func defaultContext() Context {
  	// When we reach Go 1.3 the line will read
  	//	c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"}
  	// and so on.
- 	c.ReleaseTags = []string{"go1.1"}
+ 	c.ReleaseTags = []string{"go1.1", "go1.2"}
  
  	switch os.Getenv("CGO_ENABLED") {
  	case "1":

コアとなるコードの解説

変更は src/pkg/go/build/build.go ファイルの defaultContext() 関数内の一行に集約されています。

元のコード:

	c.ReleaseTags = []string{"go1.1"}

この行は、デフォルトのビルドコンテキスト cReleaseTags フィールドを、"go1.1" という文字列を含むスライスで初期化していました。これは、Go 1.1がリリースされた時点でのGoのビルドツールが認識するリリースビルドタグが go1.1 のみであったことを意味します。

変更後のコード:

	c.ReleaseTags = []string{"go1.1", "go1.2"}

この行では、ReleaseTags スライスに "go1.2" が追加されています。これにより、Goのビルドツールは、go1.2 というビルドタグを認識し、Go 1.2以降のバージョンでコンパイルされる際に、このタグが有効であると判断するようになります。

このシンプルな変更は、GoのビルドシステムがGo 1.2のリリースを「認識」し、それに対応するビルドタグをサポートするための基盤を築きます。これにより、開発者はGo 1.2固有の機能を利用するコードを、ビルドタグを使って適切に分離し、異なるGoバージョン間でのコードの互換性と管理を容易にすることができます。

関連リンク

参考にした情報源リンク