[インデックス 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/httpCGO dependency - Stack Overflow: https://stackoverflow.com/questions/37100000/go-net-http-cgo-dependency - Go
netpackage and CGO - go.dev: https://go.dev/blog/go1.11-network (Go 1.11に関する記事ですが、netパッケージのCGO依存について言及があります) - Go
netpackage source code (fornetgoandnetcgobuild tags): https://github.com/golang/go/blob/master/src/net/conf.go (Goのソースコード内のnetパッケージのビルドタグに関する情報)