[インデックス 16684] ファイルの概要
このコミットは、Go言語の標準ライブラリsync/atomic
パッケージのテストコードからnet/http
パッケージへの依存関係を削除するものです。これにより、sync/atomic
パッケージのテストがcgo
(C言語との連携機能)に依存しなくなり、Goのビルドシステムが不安定な状態にある場合でも、sync/atomic
のテストが独立してパスすることを目指しています。
コミット
commit 20498ed772ef5791a17248f1198b58265299574e
Author: Russ Cox <rsc@golang.org>
Date: Mon Jul 1 17:27:19 2013 -0400
sync/atomic: remove test dependency on net/http
Depending on net/http means depending on cgo.
When the tree is in a shaky state it's nice to see sync/atomic
pass even if cgo or net causes broken binaries.
R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/10753044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/20498ed772ef5791a17248f1198b58265299574e
元コミット内容
sync/atomic: remove test dependency on net/http
net/http
に依存することはcgo
に依存することを意味します。
ツリーが不安定な状態にあるとき、cgo
やnet
が壊れたバイナリを引き起こしても、sync/atomic
がパスすることを確認できるのは良いことです。
変更の背景
この変更の背景には、Go言語のビルドシステムとテストの安定性への配慮があります。
net/http
とcgo
の依存関係: Go言語のnet/http
パッケージは、一部の機能(特にDNS解決など)でC言語のライブラリを呼び出すためにcgo
を使用することがあります。cgo
はGoプログラムからC言語のコードを呼び出すためのメカニズムであり、これを使用するとビルドプロセスが複雑になり、Cコンパイラや関連ライブラリの存在に依存するようになります。- ビルドの不安定性: Goの標準ライブラリ全体が開発中の場合、特に初期の段階では、
cgo
やnet
パッケージ自体に起因する問題(バグ、ビルド環境の差異、コンパイラの不整合など)が発生し、それが原因でビルドが失敗したり、生成されるバイナリが壊れたりすることがありました。 sync/atomic
の重要性:sync/atomic
パッケージは、並行処理においてアトミックな操作(不可分な操作)を提供する非常に基本的なパッケージです。これはGoの並行処理モデルの根幹をなすものであり、その正確性と安定性は極めて重要です。- テストの独立性:
sync/atomic
のような基盤となるパッケージのテストは、他の複雑なパッケージ(特にcgo
に依存するもの)の不安定性の影響を受けないようにすることが望ましいです。もしsync/atomic
のテストがnet/http
を介してcgo
に依存していると、cgo
やnet
に問題があるだけでsync/atomic
のテストが失敗し、問題の根本原因の特定が困難になる可能性があります。
このコミットは、sync/atomic
のテストがnet/http
(ひいてはcgo
)の潜在的な問題から切り離されることで、Goのビルドツリー全体が不安定な状況でも、sync/atomic
パッケージの健全性を独立して確認できるようにすることを目的としています。これにより、問題の切り分けが容易になり、開発効率が向上します。
前提知識の解説
Go言語のsync/atomic
パッケージ
sync/atomic
パッケージは、Go言語における低レベルな並行処理プリミティブを提供します。これは、複数のゴルーチン(軽量スレッド)が共有データにアクセスする際に、データ競合を防ぎ、操作の原子性(不可分性)を保証するためのものです。具体的には、以下のようなアトミック操作を提供します。
- Add: 指定された値にアトミックに加算する。
- CompareAndSwap (CAS): 指定されたメモリ位置の値が期待値と一致する場合にのみ、新しい値にアトミックに置き換える。
- Load: 指定されたメモリ位置の値をアトミックに読み込む。
- Store: 指定されたメモリ位置に値をアトミックに書き込む。
これらの操作は、通常、CPUの特殊な命令(例: x86のLOCK
プレフィックス付き命令)を利用して実装されており、ミューテックス(sync.Mutex
)のようなロック機構を使用するよりも高速で、競合が少ない場合に特に有効です。
Go言語のnet/http
パッケージ
net/http
パッケージは、HTTPクライアントとサーバーの実装を提供します。WebアプリケーションやAPIサーバーを構築する際に中心的に使用されるパッケージです。HTTPリクエストの送信、HTTPレスポンスの処理、Webサーバーの起動とルーティングなど、HTTP通信に関する高レベルな機能を提供します。
cgo
cgo
は、Go言語のプログラムからC言語のコードを呼び出すためのGoのツールです。また、C言語のプログラムからGo言語の関数を呼び出すことも可能です。cgo
を使用すると、Goで直接実装されていない既存のCライブラリを利用したり、パフォーマンスが重要な部分をCで記述したりすることができます。
cgo
を使用するGoプログラムをビルドする際には、Goコンパイラだけでなく、Cコンパイラ(通常はGCCやClang)も必要になります。これにより、ビルドプロセスが複雑になり、クロスコンパイルの難易度が上がったり、特定の環境でのビルドエラーの原因になったりすることがあります。
net/http
パッケージがcgo
に依存する例としては、DNS解決(net
パッケージの一部)が挙げられます。システムによっては、GoのネイティブなDNSリゾルバではなく、OSのCライブラリ(例: glibc
のgetaddrinfo
)を使用する方が効率的または必要となる場合があります。このような場合にcgo
が利用されます。
技術的詳細
このコミットの技術的詳細は、sync/atomic
パッケージのExampleWaitGroup
テスト関数が、net/http
パッケージの実際の機能を使用せずに、その依存関係を模倣するダミーの構造体と関数に置き換えることで実現されています。
元のコードでは、ExampleWaitGroup
関数内でnet/http.Get
関数を呼び出していましたが、これはテストの目的上、実際にHTTPリクエストを送信する必要はありませんでした。単にWaitGroup
の動作を示すためのプレースホルダーとして使用されていました。
変更後のコードでは、以下のダミー実装が導入されています。
type httpPkg struct{}
func (httpPkg) Get(url string) {}
var http httpPkg
type httpPkg struct{}
:httpPkg
という名前の空の構造体を定義します。これはnet/http
パッケージを模倣するための型です。func (httpPkg) Get(url string) {}
:httpPkg
型にGet
メソッドを定義します。このメソッドはnet/http.Get
と同じシグネチャ(url string
を引数にとり、何も返さない)を持ちますが、実際には何も処理を行いません。var http httpPkg
:httpPkg
型の変数http
を宣言します。これにより、元のコードでnet/http.Get
と書かれていた部分をhttp.Get
と書くことができるようになります。
この変更により、example_test.go
ファイルはもはやnet/http
パッケージをインポートする必要がなくなります。結果として、このテストファイルはcgo
に依存しなくなり、sync/atomic
パッケージのテストがより独立して実行できるようになります。
これは、テストの目的がWaitGroup
の動作を示すことであり、実際のネットワーク通信のテストではないため、機能的な影響はありません。しかし、ビルドシステム全体の安定性という観点からは大きな改善となります。
コアとなるコードの変更箇所
変更はsrc/pkg/sync/example_test.go
ファイルに集中しています。
--- a/src/pkg/sync/example_test.go
+++ b/src/pkg/sync/example_test.go
@@ -6,10 +6,15 @@ package sync_test
import (
"fmt"
- "net/http"
"sync"
)
+type httpPkg struct{}
+
+func (httpPkg) Get(url string) {}
+
+var http httpPkg
+
// This example fetches several URLs concurrently,
// using a WaitGroup to block until all the fetches are complete.
func ExampleWaitGroup() {
コアとなるコードの解説
- "net/http"
: 既存のnet/http
パッケージのインポートが削除されました。これがこのコミットの主要な目的であり、cgo
への間接的な依存を断ち切るためのものです。+type httpPkg struct{}
:net/http
パッケージの機能を模倣するためのダミー型httpPkg
が定義されました。+func (httpPkg) Get(url string) {}
:httpPkg
型にGet
メソッドが追加されました。このメソッドは、元のコードでnet/http.Get
が呼び出されていた箇所で、同じように呼び出せるようにするためのスタブ(空の関数)です。これにより、テストコードのロジックを変更することなく、依存関係を解消できます。+var http httpPkg
:httpPkg
型のグローバル変数http
が宣言されました。これにより、テストコード内でhttp.Get(url)
という形式でダミーのGet
メソッドを呼び出すことが可能になります。
この変更により、ExampleWaitGroup
関数内のhttp.Get(url)
の呼び出しは、実際のネットワーク通信を行うnet/http.Get
ではなく、このファイル内で定義された何もしないダミーのGet
メソッドを呼び出すことになります。これにより、テストの意図(WaitGroup
の動作確認)は保たれつつ、外部パッケージへの不要な依存が排除されました。
関連リンク
- Go言語の
sync/atomic
パッケージのドキュメント: https://pkg.go.dev/sync/atomic - Go言語の
net/http
パッケージのドキュメント: https://pkg.go.dev/net/http - Go言語の
cgo
に関するドキュメント: https://pkg.go.dev/cmd/cgo
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード(特に
src/pkg/sync/example_test.go
の変更履歴) cgo
に関する一般的な情報源(Go言語のビルドプロセスとC言語連携について)- Go言語のコミットメッセージとコードレビューコメント
[インデックス 16684] ファイルの概要
このコミットは、Go言語の標準ライブラリsync/atomic
パッケージのテストコードからnet/http
パッケージへの依存関係を削除するものです。これにより、sync/atomic
パッケージのテストがcgo
(C言語との連携機能)に依存しなくなり、Goのビルドシステムが不安定な状態にある場合でも、sync/atomic
のテストが独立してパスすることを目指しています。
コミット
commit 20498ed772ef5791a17248f1198b58265299574e
Author: Russ Cox <rsc@golang.org>
Date: Mon Jul 1 17:27:19 2013 -0400
sync/atomic: remove test dependency on net/http
Depending on net/http means depending on cgo.
When the tree is in a shaky state it's nice to see sync/atomic
pass even if cgo or net causes broken binaries.
R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/10753044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/20498ed772ef5791a17248f1198b58265299574e
元コミット内容
sync/atomic: remove test dependency on net/http
net/http
に依存することはcgo
に依存することを意味します。
ツリーが不安定な状態にあるとき、cgo
やnet
が壊れたバイナリを引き起こしても、sync/atomic
がパスすることを確認できるのは良いことです。
変更の背景
この変更の背景には、Go言語のビルドシステムとテストの安定性への配慮があります。
net/http
とcgo
の依存関係: Go言語のnet/http
パッケージは、一部の機能(特にDNS解決など)でC言語のライブラリを呼び出すためにcgo
を使用することがあります。cgo
はGoプログラムからC言語のコードを呼び出すためのメカニズムであり、これを使用するとビルドプロセスが複雑になり、Cコンパイラや関連ライブラリの存在に依存するようになります。特にUnix系システムでは、net
パッケージがDNS解決のためにシステムレベルのCライブラリ(getaddrinfo
など)を利用する際にcgo
がデフォルトで有効になることがあります。- ビルドの不安定性: Goの標準ライブラリ全体が開発中の場合、特に初期の段階では、
cgo
やnet
パッケージ自体に起因する問題(バグ、ビルド環境の差異、コンパイラの不整合など)が発生し、それが原因でビルドが失敗したり、生成されるバイナリが壊れたりすることがありました。 sync/atomic
の重要性:sync/atomic
パッケージは、並行処理においてアトミックな操作(不可分な操作)を提供する非常に基本的なパッケージです。これはGoの並行処理モデルの根幹をなすものであり、その正確性と安定性は極めて重要です。- テストの独立性:
sync/atomic
のような基盤となるパッケージのテストは、他の複雑なパッケージ(特にcgo
に依存するもの)の不安定性の影響を受けないようにすることが望ましいです。もしsync/atomic
のテストがnet/http
を介してcgo
に依存していると、cgo
やnet
に問題があるだけでsync/atomic
のテストが失敗し、問題の根本原因の特定が困難になる可能性があります。
このコミットは、sync/atomic
のテストがnet/http
(ひいてはcgo
)の潜在的な問題から切り離されることで、Goのビルドツリー全体が不安定な状況でも、sync/atomic
パッケージの健全性を独立して確認できるようにすることを目的としています。これにより、問題の切り分けが容易になり、開発効率が向上します。
前提知識の解説
Go言語のsync/atomic
パッケージ
sync/atomic
パッケージは、Go言語における低レベルな並行処理プリミティブを提供します。これは、複数のゴルーチン(軽量スレッド)が共有データにアクセスする際に、データ競合を防ぎ、操作の原子性(不可分性)を保証するためのものです。具体的には、以下のようなアトミック操作を提供します。
- Add: 指定された値にアトミックに加算する。
- CompareAndSwap (CAS): 指定されたメモリ位置の値が期待値と一致する場合にのみ、新しい値にアトミックに置き換える。
- Load: 指定されたメモリ位置の値をアトミックに読み込む。
- Store: 指定されたメモリ位置に値をアトミックに書き込む。
これらの操作は、通常、CPUの特殊な命令(例: x86のLOCK
プレフィックス付き命令)を利用して実装されており、ミューテックス(sync.Mutex
)のようなロック機構を使用するよりも高速で、競合が少ない場合に特に有効です。
Go言語のnet/http
パッケージ
net/http
パッケージは、HTTPクライアントとサーバーの実装を提供します。WebアプリケーションやAPIサーバーを構築する際に中心的に使用されるパッケージです。HTTPリクエストの送信、HTTPレスポンスの処理、Webサーバーの起動とルーティングなど、HTTP通信に関する高レベルな機能を提供します。
cgo
cgo
は、Go言語のプログラムからC言語のコードを呼び出すためのGoのツールです。また、C言語のプログラムからGo言語の関数を呼び出すことも可能です。cgo
を使用すると、Goで直接実装されていない既存のCライブラリを利用したり、パフォーマンスが重要な部分をCで記述したりすることができます。
cgo
を使用するGoプログラムをビルドする際には、Goコンパイラだけでなく、Cコンパイラ(通常はGCCやClang)も必要になります。これにより、ビルドプロセスが複雑になり、クロスコンパイルの難易度が上がったり、特定の環境でのビルドエラーの原因になったりすることがあります。
net/http
パッケージがcgo
に依存する例としては、DNS解決(net
パッケージの一部)が挙げられます。システムによっては、GoのネイティブなDNSリゾルバではなく、OSのCライブラリ(例: glibc
のgetaddrinfo
)を使用する方が効率的または必要となる場合があります。このような場合にcgo
が利用されます。ただし、Goには純粋なGoで実装されたDNSリゾルバも存在し、CGO_ENABLED=0
環境変数を設定したり、netgo
ビルドタグを使用したりすることで、CGOへの依存を回避することも可能です。
技術的詳細
このコミットの技術的詳細は、sync/atomic
パッケージのExampleWaitGroup
テスト関数が、net/http
パッケージの実際の機能を使用せずに、その依存関係を模倣するダミーの構造体と関数に置き換えることで実現されています。
元のコードでは、ExampleWaitGroup
関数内でnet/http.Get
関数を呼び出していましたが、これはテストの目的上、実際にHTTPリクエストを送信する必要はありませんでした。単にWaitGroup
の動作を示すためのプレースホルダーとして使用されていました。
変更後のコードでは、以下のダミー実装が導入されています。
type httpPkg struct{}
func (httpPkg) Get(url string) {}
var http httpPkg
type httpPkg struct{}
:httpPkg
という名前の空の構造体を定義します。これはnet/http
パッケージを模倣するための型です。func (httpPkg) Get(url string) {}
:httpPkg
型にGet
メソッドを定義します。このメソッドはnet/http.Get
と同じシグネチャ(url string
を引数にとり、何も返さない)を持ちますが、実際には何も処理を行いません。var http httpPkg
:httpPkg
型の変数http
を宣言します。これにより、元のコードでnet/http.Get
と書かれていた部分をhttp.Get
と書くことができるようになります。
この変更により、example_test.go
ファイルはもはやnet/http
パッケージをインポートする必要がなくなります。結果として、このテストファイルはcgo
に依存しなくなり、sync/atomic
パッケージのテストがより独立して実行できるようになります。
これは、テストの目的がWaitGroup
の動作を示すことであり、実際のネットワーク通信のテストではないため、機能的な影響はありません。しかし、ビルドシステム全体の安定性という観点からは大きな改善となります。
コアとなるコードの変更箇所
変更はsrc/pkg/sync/example_test.go
ファイルに集中しています。
--- a/src/pkg/sync/example_test.go
+++ b/src/pkg/sync/example_test.go
@@ -6,10 +6,15 @@ package sync_test
import (
"fmt"
- "net/http"
"sync"
)
+type httpPkg struct{}
+
+func (httpPkg) Get(url string) {}
+
+var http httpPkg
+
// This example fetches several URLs concurrently,
// using a WaitGroup to block until all the fetches are complete.
func ExampleWaitGroup() {
コアとなるコードの解説
- "net/http"
: 既存のnet/http
パッケージのインポートが削除されました。これがこのコミットの主要な目的であり、cgo
への間接的な依存を断ち切るためのものです。+type httpPkg struct{}
:net/http
パッケージの機能を模倣するためのダミー型httpPkg
が定義されました。+func (httpPkg) Get(url string) {}
:httpPkg
型にGet
メソッドが追加されました。このメソッドは、元のコードでnet/http.Get
が呼び出されていた箇所で、同じように呼び出せるようにするためのスタブ(空の関数)です。これにより、テストコードのロジックを変更することなく、依存関係を解消できます。+var http httpPkg
:httpPkg
型のグローバル変数http
が宣言されました。これにより、テストコード内でhttp.Get(url)
という形式でダミーのGet
メソッドを呼び出すことが可能になります。
この変更により、ExampleWaitGroup
関数内のhttp.Get(url)
の呼び出しは、実際のネットワーク通信を行うnet/http.Get
ではなく、このファイル内で定義された何もしないダミーのGet
メソッドを呼び出すことになります。これにより、テストの意図(WaitGroup
の動作確認)は保たれつつ、外部パッケージへの不要な依存が排除されました。
関連リンク
- Go言語の
sync/atomic
パッケージのドキュメント: https://pkg.go.dev/sync/atomic - Go言語の
net/http
パッケージのドキュメント: https://pkg.go.dev/net/http - Go言語の
cgo
に関するドキュメント: https://pkg.go.dev/cmd/cgo
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード(特に
src/pkg/sync/example_test.go
の変更履歴) cgo
に関する一般的な情報源(Go言語のビルドプロセスとC言語連携について)- Go言語のコミットメッセージとコードレビューコメント
- Go
net/http
CGO dependency - Stack Overflow: https://stackoverflow.com/questions/37100000/go-net-http-cgo-dependency - Go
net
package and CGO - go.dev: https://go.dev/blog/go1.11-network (Go 1.11に関する記事ですが、net
パッケージのCGO依存について言及があります) - Go
net
package source code (fornetgo
andnetcgo
build tags): https://github.com/golang/go/blob/master/src/net/conf.go (Goのソースコード内のnet
パッケージのビルドタグに関する情報)