[インデックス 16530] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージにおいて、Cgoに依存しない「純粋なGo」実装をビルドするための新しいビルドタグnetgo
を導入するものです。これにより、Cgoの依存関係を排除し、クロスコンパイルや静的リンクされたバイナリの生成を容易にすることが目的とされています。
コミット
- コミットハッシュ:
06f55f50097293027a4634ba88140c75702c6a5d
- Author: Shenghou Ma minux.ma@gmail.com
- Date: Tue Jun 11 02:55:16 2013 +0800
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/06f55f50097293027a4634ba88140c75702c6a5d
元コミット内容
net: introduce netgo build tag to build a pure Go net package.
Fixes #4078.
R=golang-dev, bradfitz, rsc, iant
CC=golang-dev
https://golang.org/cl/7100050
変更の背景
Go言語のnet
パッケージは、ネットワーク関連の操作(DNSルックアップなど)を行う際に、OSのネイティブなCライブラリ(例えばglibcのgetaddrinfo
など)を利用するためにCgoを使用することがあります。これは、特にDNS解決において、システムの設定(/etc/resolv.conf
など)を尊重し、より堅牢な動作を保証するためです。
しかし、Cgoを使用すると、以下のような問題が発生する可能性があります。
- クロスコンパイルの複雑化: 異なるOSやアーキテクチャ向けにGoプログラムをコンパイルする際、Cgoが依存するCライブラリもターゲット環境に合わせてビルド・リンクする必要があり、プロセスが複雑になります。
- 静的リンクの困難さ: Cgoを使用すると、生成されるバイナリは動的リンクされるCライブラリに依存することが多く、完全に静的にリンクされた単一のバイナリを生成するのが難しくなります。これは、コンテナ環境や最小限の実行環境でGoアプリケーションをデプロイする際に問題となることがあります。
- Cライブラリの依存性: 特定のCライブラリのバージョンや存在に依存するため、デプロイ環境での互換性の問題が発生する可能性があります。
このコミットは、これらの問題を解決するために、Cgoに依存しない純粋なGo実装のnet
パッケージをビルドするオプションを提供することを目的としています。これにより、開発者は必要に応じてCgoの依存関係を排除したバイナリを生成できるようになります。
前提知識の解説
Cgo
Cgoは、GoプログラムからC言語のコードを呼び出すためのGoの機能です。Goのソースファイル内にCコードを埋め込んだり、既存のCライブラリをリンクしたりすることができます。Goの標準ライブラリの多くは、パフォーマンスやOSとの連携のためにCgoを利用しています。例えば、os/user
パッケージやnet
パッケージの一部は、システムコールやネイティブライブラリの機能を利用するためにCgoを使用しています。
Goのビルドタグ(Build Tags)
Goのビルドタグは、Goのソースファイルを条件付きでコンパイルするためのメカニズムです。ソースファイルの先頭に// +build tagname
のような形式でコメントを記述することで、特定のタグが有効な場合にのみそのファイルをコンパイルするように指定できます。
// +build tag1
:tag1
が有効な場合にコンパイルされます。// +build !tag2
:tag2
が有効でない場合にコンパイルされます。// +build tag1,tag2
:tag1
とtag2
の両方が有効な場合にコンパイルされます(AND条件)。// +build tag1 tag2
:tag1
またはtag2
のいずれかが有効な場合にコンパイルされます(OR条件)。
ビルド時にgo build -tags tagname
のように-tags
オプションを指定することで、特定のビルドタグを有効にできます。
純粋なGo (pure Go
)
Go言語の文脈で「純粋なGo」とは、Cgoを一切使用せず、Go言語のみで実装されたコードやパッケージを指します。純粋なGoで書かれたプログラムは、CコンパイラやCライブラリへの依存がなく、クロスコンパイルが容易で、完全に静的にリンクされたバイナリを生成しやすいという利点があります。
net
パッケージの場合、DNS解決などの一部の機能はCgoに依存していましたが、このコミットによって、Cgoを使用しない代替実装(Go言語のみで書かれたDNSリゾルバなど)を選択できるようになります。
技術的詳細
このコミットは、netgo
という新しいビルドタグを導入することで、net
パッケージのビルドプロセスを制御します。
Goのnet
パッケージには、Cgoを使用してネットワーク関連のシステムコールやライブラリ関数を呼び出すためのファイル(例: cgo_bsd.go
, cgo_linux.go
など)と、Cgoを使用しない純粋なGoで実装された代替ファイル(例: cgo_stub.go
)が存在します。
通常、GoはターゲットOSに応じて適切なCgoファイルを選択してコンパイルします。しかし、netgo
タグが有効な場合、Cgoに依存するファイルはコンパイルから除外され、代わりに純粋なGoで書かれた代替実装が使用されるようになります。
具体的には、以下の変更が行われています。
-
cgo_*.go
ファイルへの!netgo
タグの追加:src/pkg/net/cgo_bsd.go
,src/pkg/net/cgo_linux.go
,src/pkg/net/cgo_netbsd.go
,src/pkg/net/cgo_openbsd.go
,src/pkg/net/cgo_unix.go
といったCgoに依存するファイルには、// +build !netgo
というビルドタグが追加されました。これは、「netgo
タグが有効でない場合にのみこのファイルをコンパイルする」という意味です。 また、cgo_linux.go
,cgo_netbsd.go
,cgo_openbsd.go
には既存の+build cgo
に加えて!netgo
が追加され、+build cgo,!netgo
となっています。これは、「Cgoが有効で、かつnetgo
が有効でない場合にのみこのファイルをコンパイルする」という意味になります。 -
cgo_stub.go
ファイルへのnetgo
タグの追加:src/pkg/net/cgo_stub.go
は、Cgoが利用できない環境や、Cgoを使用しない場合にフォールバックとして使用されるスタブ実装のファイルです。このファイルには、既存の// +build !cgo
に加えてnetgo
が追加され、// +build !cgo netgo
となりました。これは、「Cgoが有効でない場合、またはnetgo
タグが有効な場合にこのファイルをコンパイルする」という意味になります。
これらの変更により、go build -tags netgo
コマンドを実行すると、Cgoに依存するnet
パッケージのコードがコンパイルから除外され、純粋なGoで実装されたネットワーク機能が使用されるようになります。これにより、Cライブラリへの依存がない、完全にGoだけで構成されたバイナリを生成することが可能になります。
コアとなるコードの変更箇所
このコミットでは、主にsrc/pkg/net
ディレクトリ内のCgo関連のGoソースファイルのビルドタグが変更されています。
doc/go1.2.txt
: Go 1.2のリリースノートにnetgo
タグの導入が追記されました。src/pkg/net/cgo_bsd.go
:// +build !netgo
が追加されました。src/pkg/net/cgo_linux.go
:// +build cgo,!netgo
に変更されました。src/pkg/net/cgo_netbsd.go
:// +build cgo,!netgo
に変更されました。src/pkg/net/cgo_openbsd.go
:// +build cgo,!netgo
に変更されました。src/pkg/net/cgo_stub.go
:// +build !cgo netgo
に変更されました。src/pkg/net/cgo_unix.go
:// +build !netgo
が追加されました。
コアとなるコードの解説
変更の核心は、Goのビルドタグの論理的な組み合わせにあります。
cgo_bsd.go
, cgo_unix.go
の変更
--- a/src/pkg/net/cgo_bsd.go
+++ b/src/pkg/net/cgo_bsd.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !netgo
// +build darwin freebsd
package net
これらのファイルは、BSD系のOS(Darwin/macOS, FreeBSD)や一般的なUnix系OS向けのCgo実装を含んでいます。// +build !netgo
が追加されたことで、netgo
タグが指定されたビルドではこれらのファイルがコンパイルされなくなります。これにより、Cgoに依存するネットワーク機能が除外されます。
cgo_linux.go
, cgo_netbsd.go
, cgo_openbsd.go
の変更
--- a/src/pkg/net/cgo_linux.go
+++ b/src/pkg/net/cgo_linux.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build cgo,!netgo
+
package net
これらのファイルは、Linux, NetBSD, OpenBSD向けのCgo実装を含んでいます。既存の+build cgo
に加えて,!netgo
が追加されました。これは、Cgoが有効であり、かつnetgo
タグが有効でない場合にのみこれらのファイルがコンパイルされることを意味します。つまり、netgo
タグが有効な場合は、Cgoが有効であってもこれらのファイルはコンパイルされません。
cgo_stub.go
の変更
--- a/src/pkg/net/cgo_stub.go
+++ b/src/pkg/net/cgo_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !cgo
+// +build !cgo netgo
// Stub cgo routines for systems that do not use cgo to do network lookups.
cgo_stub.go
は、Cgoが利用できない環境(例: GOARCH=js
など)や、Cgoを使用しない場合にフォールバックとして使用されるスタブ実装です。元のタグは// +build !cgo
でした。これにnetgo
が追加され、// +build !cgo netgo
となりました。これは、「Cgoが有効でない場合、またはnetgo
タグが有効な場合」にこのファイルがコンパイルされることを意味します。
この変更により、go build -tags netgo
を実行すると、Cgoに依存するファイルが除外され、代わりにcgo_stub.go
がコンパイルされるようになります。これにより、net
パッケージはCgoの依存なしに動作し、純粋なGoで実装されたネットワーク機能(例えば、Go自身のDNSリゾルバ)を使用するようになります。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/06f55f50097293027a4634ba88140c75702c6a5d
- Go Code Review (CL): https://golang.org/cl/7100050
- コミットメッセージに記載されているIssue
#4078
については、公開されているGoのIssueトラッカーでは直接的な情報を見つけることができませんでした。
参考にした情報源リンク
- Go言語のビルドタグに関する公式ドキュメントやブログ記事 (一般的なGoのビルドタグの動作について)
- Cgoに関するGo言語の公式ドキュメント (Cgoの基本的な概念と使用法について)
- Goの
net
パッケージの内部実装に関する情報 (Cgoがどのように利用されているかについて)