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

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

このコミットは、Go言語の標準ライブラリnetパッケージにおけるWindowsビルドの問題を修正するためのものです。具体的には、テストヘルパー関数であるtestUnixAddrsrc/pkg/net/unix_test.goからsrc/pkg/net/protoconn_test.goへ移動されました。この変更により、Windows環境でのビルドが正常に行われるようになり、クロスプラットフォーム対応が改善されました。

コミット

commit b767556dd751bd99cc57a528df6d9f3ec7df4b18
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Sun Mar 3 19:10:59 2013 +0900

    net: fix windows build
    
    R=golang-dev, minux.ma
    CC=golang-dev
    https://golang.org/cl/7429049
---
 src/pkg/net/protoconn_test.go | 13 +++++++++++++
 src/pkg/net/unix_test.go      | 13 -------------\n 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/pkg/net/protoconn_test.go b/src/pkg/net/protoconn_test.go
index 74ae320fe3..de0c2c00a6 100644
--- a/src/pkg/net/protoconn_test.go
+++ b/src/pkg/net/protoconn_test.go
@@ -8,12 +8,25 @@
 package net
 
 import (
+	"io/ioutil"
 	"os"
 	"runtime"
 	"testing"
 	"time"
 )
 
+// testUnixAddr uses ioutil.TempFile to get a name that is unique.
+func testUnixAddr() string {
+	f, err := ioutil.TempFile("", "nettest")
+	if err != nil {
+		panic(err)
+	}
+	addr := f.Name()
+	f.Close()
+	os.Remove(addr)
+	return addr
+}
+
 var condFatalf = func() func(*testing.T, string, ...interface{}) {
 	// A few APIs are not implemented yet on both Plan 9 and Windows.
 	switch runtime.GOOS {
diff --git a/src/pkg/net/unix_test.go b/src/pkg/net/unix_test.go
index dda717ea93..2eaabe86e4 100644
--- a/src/pkg/net/unix_test.go
+++ b/src/pkg/net/unix_test.go
@@ -8,7 +8,6 @@ package net
 
 import (
 	"bytes"
-	"io/ioutil"
 	"os"
 	"reflect"
 	"runtime"
@@ -17,18 +16,6 @@ import (
 	"time"
 )
 
-// testUnixAddr uses ioutil.TempFile to get a name that is unique.
-func testUnixAddr() string {
-	f, err := ioutil.TempFile("", "nettest")
-	if err != nil {
-		panic(err)
-	}
-	addr := f.Name()
-	f.Close()
-	os.Remove(addr)
-	return addr
-}
-
 func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
 	addr := testUnixAddr()
 	la, err := ResolveUnixAddr("unixgram", addr)

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

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

元コミット内容

コミットメッセージは非常に簡潔に「net: fix windows build」と述べられています。これは、netパッケージのWindowsビルドに関する問題を修正したことを意味します。

変更の背景

Go言語はクロスプラットフォーム開発を強く意識しており、様々なオペレーティングシステム(OS)で動作するように設計されています。しかし、OSによっては特定の機能が利用できなかったり、動作が異なったりすることがあります。

このコミットの背景には、netパッケージのテストコードがWindows環境でビルドエラーを引き起こしていた問題があります。src/pkg/net/unix_test.goは、その名の通りUnix系OSに特化した機能(Unixドメインソケットなど)のテストを含んでいます。Windowsではこれらの機能がサポートされていないか、動作が異なるため、unix_test.go内のコードがWindowsビルド時に問題を引き起こす可能性がありました。

testUnixAddr関数は、テストのために一時的なUnixドメインソケットアドレス(ファイルパス)を生成するヘルパー関数です。この関数自体はOSに依存しない汎用的なファイル操作(一時ファイルの作成と削除)を行いますが、それが含まれるunix_test.goファイルがWindowsビルドの対象外となるか、あるいはunix_test.goが依存する他のUnix固有のコードがWindowsで問題を起こしていた可能性があります。

protoconn_test.goは、より汎用的なプロトコルコネクションに関するテストを含んでおり、おそらくWindowsを含む全てのプラットフォームでビルドされることを意図しています。testUnixAddr関数がprotoconn_test.goに移動されたのは、この関数がprotoconn_test.go内のテストでも必要とされており、かつprotoconn_test.goがWindowsでもビルドされることで、Windowsビルド時の依存関係の問題を解消するためと考えられます。これにより、testUnixAddrがWindows環境でも利用可能になり、netパッケージ全体のテストがWindowsで正常に実行できるようになりました。

前提知識の解説

  • Go言語のテストファイル (_test.go): Go言語では、テストコードは対象となるソースファイルと同じディレクトリに_test.goというサフィックスを持つファイルとして配置されます。go testコマンドを実行すると、これらのファイルが自動的に検出され、テストが実行されます。
  • io/ioutilパッケージ (Go 1.16以降はosパッケージへ移行):
    • ioutil.TempFile(dir, pattern string) (f *os.File, err error): 一時ファイルを作成し、その*os.Fileとエラーを返します。dirが空文字列の場合、システムのデフォルトの一時ディレクトリが使用されます。patternはファイル名のプレフィックスとして使用されます。この関数は、テストなどで一時的なリソースが必要な場合に便利です。
    • 補足: Go 1.16以降、io/ioutilパッケージの機能はosパッケージやioパッケージに統合されました。ioutil.TempFileは現在os.CreateTempに相当します。このコミットは2013年のものであり、当時はio/ioutilが標準的な使い方でした。
  • osパッケージ:
    • os.Remove(name string) error: 指定されたパスのファイルまたは空のディレクトリを削除します。
  • runtime.GOOS: runtimeパッケージは、Goプログラムが実行されているシステムに関する情報を取得するための機能を提供します。runtime.GOOSは、プログラムがビルドされたオペレーティングシステムの名前(例: "linux", "windows", "darwin"など)を文字列で返します。これにより、コード内でOS固有の処理を条件分岐させることができます。
  • Goのクロスコンパイルとビルドタグ: Goは異なるOSやアーキテクチャ向けに簡単にコンパイルできるクロスコンパイル機能を持ちます。また、ファイル名に_windows.go_unix.goのようなビルドタグを含めることで、特定のOSでのみコンパイルされるコードを記述できます。unix_test.goのようなファイルは、その内容からUnix系OSでのみ関連するテストが含まれていると推測できます。
  • netパッケージ: Go言語の標準ライブラリで、ネットワークI/Oプリミティブを提供します。TCP/IP、UDP、Unixドメインソケットなどのネットワークプログラミングをサポートします。
  • Unixドメインソケット: 同じホスト上のプロセス間通信(IPC)に使用されるソケットの一種です。ファイルシステム上のパス名(例: /tmp/mysocket)に関連付けられます。Windowsでは、Unixドメインソケットのサポートは比較的新しく、古いバージョンでは利用できませんでした。

技術的詳細

このコミットの技術的な核心は、テストヘルパー関数の移動によるクロスプラットフォームビルドの修正です。

  1. testUnixAddr関数の役割: この関数は、テスト実行中に一時的なファイルパスを生成するために使用されます。特に、Unixドメインソケットのテストでは、ソケットがファイルシステム上のパスに関連付けられるため、テストごとにユニークなパスが必要になります。

    • ioutil.TempFile("", "nettest"): システムの一時ディレクトリ内にnettestというプレフィックスを持つユニークな一時ファイルを作成します。
    • f.Name(): 作成された一時ファイルの絶対パスを取得します。
    • f.Close(): ファイルを閉じます。
    • os.Remove(addr): ioutil.TempFileはファイルを作成しますが、testUnixAddrの目的は「ユニークなファイル名」を取得することであり、実際にそのファイル自体を保持することではありません。そのため、名前を取得した直後にファイルを削除しています。これにより、テストが実際にそのパスを使用してソケットを作成できるようになります。
  2. 移動の理由:

    • 元の場所であるsrc/pkg/net/unix_test.goは、Unixドメインソケットなど、Unix系OSに特化した機能のテストを含んでいます。Windows環境では、これらのテストファイル全体がビルド対象から除外されるか、あるいはそのファイルが依存するUnix固有のAPIがWindowsで利用できないためにビルドエラーが発生していた可能性があります。
    • src/pkg/net/protoconn_test.goは、より汎用的なネットワークプロトコルに関するテストを含んでおり、Windowsを含むすべてのサポート対象プラットフォームでビルドされることが期待されます。
    • testUnixAddr関数自体は、一時ファイルの作成と削除というOSに依存しない汎用的な操作を行っています。そのため、この関数がprotoconn_test.goに移動されたことで、Windows環境でもこのヘルパー関数が利用可能になり、protoconn_test.go内のテストが正常にビルド・実行できるようになりました。これは、protoconn_test.go内のテストがtestUnixAddrを必要としていたことを示唆しています。
  3. Windowsビルド修正のメカニズム: この変更により、testUnixAddrがWindowsビルド時にアクセスできないunix_test.goから、Windowsでもビルドされるprotoconn_test.goへ移動されたことで、Windows環境でのコンパイルエラーが解消されました。これは、Goのビルドシステムがファイル名やビルドタグに基づいて特定のファイルを特定のOS向けビルドに含める/含めないという挙動を利用した、典型的なクロスプラットフォーム対応の修正パターンです。

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

変更は2つのファイルにまたがっています。

  1. src/pkg/net/protoconn_test.go:

    • import文に"io/ioutil"が追加されました。
    • testUnixAddr()関数が新規に追加されました。
  2. src/pkg/net/unix_test.go:

    • import文から"io/ioutil"が削除されました。
    • testUnixAddr()関数が完全に削除されました。

実質的には、testUnixAddr()関数がunix_test.goからprotoconn_test.goへ移動された形です。

コアとなるコードの解説

移動されたtestUnixAddr関数は以下の通りです。

// testUnixAddr uses ioutil.TempFile to get a name that is unique.
func testUnixAddr() string {
	// ioutil.TempFileを使用して、システムの一時ディレクトリ内に
	// "nettest"というプレフィックスを持つユニークな一時ファイルを作成します。
	// この関数はファイル自体を作成しますが、ここではそのファイル名だけが必要です。
	f, err := ioutil.TempFile("", "nettest")
	if err != nil {
		// エラーが発生した場合はパニック(プログラムの異常終了)を引き起こします。
		// テストヘルパー関数なので、テストの失敗として扱われます。
		panic(err)
	}
	// 作成された一時ファイルの絶対パスを取得します。
	addr := f.Name()
	// ファイルを閉じます。
	f.Close()
	// 取得したパスのファイルをすぐに削除します。
	// これは、この関数が「ユニークなファイル名」を提供することが目的であり、
	// 実際にファイルが存在する必要がないためです。
	// テストコードがこのパスを使用して、後で実際のソケットファイルを作成します。
	os.Remove(addr)
	// 生成されたユニークなファイルパスを返します。
	return addr
}

この関数は、ネットワークテスト、特にUnixドメインソケットのテストにおいて、テストごとに異なるソケットパスを確保するために不可欠なユーティリティです。一時ファイルを作成し、その名前だけを利用してすぐに削除することで、テスト環境をクリーンに保ちつつ、ユニークなリソース名を提供します。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント(osパッケージ、io/ioutilパッケージ、runtimeパッケージなど)
  • Go言語のクロスコンパイルに関する一般的な情報
  • Unixドメインソケットに関する一般的な情報
  • Web検索結果: golang.org/cl/7429049に関する情報 (Go Code Reviewシステム)