[インデックス 10913] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージにおけるWindowsビルドの問題を修正するものです。具体的には、timeoutError
型とその関連変数をsrc/pkg/net/fd.go
からsrc/pkg/net/net.go
へ移動することで、Windows環境でのコンパイルエラーを解消しています。
コミット
commit 01507b9ad168b98a1d528e6039f98a13d633034e
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Dec 20 14:32:33 2011 -0800
net: fix Windows build
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5505048
---
src/pkg/net/fd.go | 8 --------
src/pkg/net/net.go | 8 ++++++++
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go
index 5318c51c9a..bcd04a0ad8 100644
--- a/src/pkg/net/fd.go
+++ b/src/pkg/net/fd.go
@@ -377,14 +377,6 @@ func (fd *netFD) CloseWrite() error {
return fd.shutdown(syscall.SHUT_WR)
}
-type timeoutError struct{}
-
-func (e *timeoutError) Error() string { return "i/o timeout" }
-func (e *timeoutError) Timeout() bool { return true }
-func (e *timeoutError) Temporary() bool { return true }
-
-var errTimeout error = &timeoutError{}
-
func (fd *netFD) Read(p []byte) (n int, err error) {
if fd == nil {
return 0, os.EINVAL
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index 48f0ae791c..b236dfdb1d 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -157,6 +157,14 @@ func (e *OpError) Timeout() bool {
return ok && t.Timeout()\n }\n \n+type timeoutError struct{}\n+\n+func (e *timeoutError) Error() string { return "i/o timeout" }\n+func (e *timeoutError) Timeout() bool { return true }\n+func (e *timeoutError) Temporary() bool { return true }\n+\n+var errTimeout error = &timeoutError{}\n+\n type AddrError struct {\n \tErr string\n \tAddr string\n```
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/01507b9ad168b98a1d528e6039f98a13d633034e](https://github.com/golang/go/commit/01507b9ad168b98a1d528e6039f98a13d633034e)
## 元コミット内容
このコミットは、Go言語の`net`パッケージにおけるWindowsビルドの不具合を修正することを目的としています。具体的には、`timeoutError`というエラー型とそのインスタンスである`errTimeout`の定義を、`src/pkg/net/fd.go`から`src/pkg/net/net.go`へ移動しています。
## 変更の背景
Go言語はクロスプラットフォーム対応を重視しており、異なるオペレーティングシステム(OS)で同じコードベースが問題なく動作・コンパイルされることを目指しています。このコミットが行われた2011年当時、Go言語はまだ発展途上にあり、OS固有のビルド問題が発生することは珍しくありませんでした。
`timeoutError`は、ネットワーク操作におけるタイムアウトを示すエラー型です。このような汎用的なエラー型は、`net`パッケージ内の複数のファイルや、場合によっては他のパッケージからも参照される可能性があります。
`src/pkg/net/fd.go`はファイルディスクリプタ(File Descriptor)に関連する低レベルのネットワーク操作を扱うファイルであり、OS固有の実装を含むことがあります。一方、`src/pkg/net/net.go`は`net`パッケージの主要な定義や汎用的な機能を含む、より高レベルかつ共通的なファイルです。
Windows環境でのビルド時に、`fd.go`に定義されていた`timeoutError`が、他のファイルやモジュールから正しく参照できない、あるいはリンケージの問題を引き起こす可能性がありました。これは、Goのパッケージ構造やコンパイルの仕組み、特にWindowsにおけるシンボル解決の特性に起因するものであったと考えられます。`timeoutError`のような基本的なエラー型は、パッケージ全体で共通して利用されるべきであり、特定のOSに依存する可能性のある`fd.go`ではなく、より汎用的な`net.go`に配置することが適切であるという判断がなされたと推測されます。
## 前提知識の解説
### Go言語の`net`パッケージ
`net`パッケージは、Go言語の標準ライブラリの一部であり、ネットワークI/O機能を提供します。TCP/IP、UDP、Unixドメインソケットなどのネットワークプロトコルを扱うためのインターフェースや型が含まれています。ソケットの作成、接続、データの送受信、リスニングなどの機能を提供し、Goアプリケーションでネットワーク通信を行う際の基盤となります。
### `timeoutError`型とエラーインターフェース
Go言語では、エラーは`error`インターフェースによって表現されます。このインターフェースは、`Error() string`というメソッドを一つだけ持ちます。
`timeoutError`は、この`error`インターフェースを実装したカスタムエラー型です。さらに、Go 1.10以降で導入された`net.Error`インターフェース(当時はまだ存在しないが、同様の概念はあった)が持つ`Timeout() bool`メソッドと`Temporary() bool`メソッドも実装しています。
* `Error() string`: エラーメッセージを返します。ここでは"i/o timeout"を返します。
* `Timeout() bool`: そのエラーがタイムアウトによるものかどうかを示します。`true`を返します。
* `Temporary() bool`: そのエラーが一時的なものであり、再試行によって解決する可能性があるかどうかを示します。`true`を返します。
このようなカスタムエラー型を定義することで、エラーの種類を詳細に判別し、それに応じた処理(例:タイムアウトなら再試行する、など)を実装することが可能になります。
### `syscall.SHUT_WR`
`syscall`パッケージは、OSのシステムコールへの低レベルなインターフェースを提供します。`syscall.SHUT_WR`は、ソケットのシャットダウン操作において、書き込み側(送信側)のみをシャットダウンすることを示す定数です。`fd.CloseWrite()`メソッド内で使用されており、ソケットの書き込みチャネルを閉じます。
### Goのパッケージとビルドシステム
Go言語のコードはパッケージに分割され、各パッケージは通常、独自のディレクトリに配置されます。パッケージ内のファイルは、同じパッケージ名を持つ限り、互いに定義を参照できます。しかし、異なるパッケージ間での参照や、OS固有のビルドタグ(例:`// +build windows`)を持つファイルが存在する場合、ビルドプロセスはより複雑になります。
このコミットの背景にある問題は、おそらくWindows環境でのコンパイル時に、`fd.go`が`timeoutError`を定義しているにもかかわらず、その定義が`net`パッケージ内の他の部分や、`net`パッケージを利用する外部のコードから正しく「見えない」状態になっていたことに関連していると考えられます。これは、GoのコンパイラやリンカがWindows上で特定のシンボル解決の順序や可視性のルールを適用した結果かもしれません。
## 技術的詳細
このコミットの技術的な核心は、`timeoutError`型とそのインスタンス`errTimeout`の定義場所の変更です。
元のコードでは、`src/pkg/net/fd.go`内に`timeoutError`型と`errTimeout`変数が定義されていました。`fd.go`は、ファイルディスクリプタを介した低レベルなネットワークI/O操作を扱うファイルであり、OS固有のコードを含むことがあります。
```go
// src/pkg/net/fd.go (変更前)
type timeoutError struct{}
func (e *timeoutError) Error() string { return "i/o timeout" }
func (e *timeoutError) Timeout() bool { return true }
func (e *timeoutError) Temporary() bool { return true }
var errTimeout error = &timeoutError{}
この定義がWindowsビルドで問題を引き起こした原因として、以下の可能性が考えられます。
- シンボル解決の問題: Windowsのリンカが、
fd.go
内で定義されたtimeoutError
を、net
パッケージ内の他のファイル(例:net.go
)や、net
パッケージを利用する外部のコードから正しく解決できなかった。これは、GoのビルドシステムがWindows上で特定のファイルやパッケージのロード順序に依存していたり、特定のOS固有のビルドタグ(例:// +build windows
)がfd.go
に適用されており、その結果としてtimeoutError
の定義が特定のビルド環境でのみ利用可能になっていた、といった状況が考えられます。 - 依存関係の循環または不整合:
fd.go
がnet.go
に依存し、かつnet.go
がtimeoutError
を参照する必要がある場合、timeoutError
がfd.go
に定義されていると、依存関係の循環や、net.go
がtimeoutError
の定義を認識する前に参照しようとする不整合が生じた可能性があります。 - 汎用性の欠如:
timeoutError
はネットワーク操作全般で発生しうる汎用的なエラーであり、特定の低レベルなファイルディスクリプタ操作に限定されるべきではありません。net.go
はnet
パッケージのコアとなる定義を含むため、このような汎用的なエラー型を配置するのに適した場所です。これにより、パッケージ内のどのファイルからでも、あるいはnet
パッケージをインポートする他のパッケージからでも、timeoutError
を安定して参照できるようになります。
コミットでは、timeoutError
型とその関連変数をsrc/pkg/net/net.go
に移動しました。
// src/pkg/net/net.go (変更後)
type timeoutError struct{}
func (e *timeoutError) Error() string { return "i/o timeout" }
func (e *timeoutError) Timeout() bool { return true }
func (e *timeoutError) Temporary() bool { return true }
var errTimeout error = &timeoutError{}
この変更により、timeoutError
の定義がnet
パッケージのより中心的なファイルに配置され、Windows環境でのビルド時に発生していたシンボル解決やリンケージの問題が解消されたと考えられます。これは、Goのクロスコンパイルや特定のOSでのビルドの挙動に関する深い理解に基づいた修正と言えます。
コアとなるコードの変更箇所
このコミットによるコードの変更は、以下の2つのファイルにわたります。
-
src/pkg/net/fd.go
:timeoutError
型の定義が削除されました。Error() string
、Timeout() bool
、Temporary() bool
メソッドの実装が削除されました。errTimeout
変数の宣言と初期化が削除されました。 これらの変更により、fd.go
からtimeoutError
に関するコードが完全に削除されています。
-
src/pkg/net/net.go
:timeoutError
型の定義が追加されました。Error() string
、Timeout() bool
、Temporary() bool
メソッドの実装が追加されました。errTimeout
変数の宣言と初期化が追加されました。 これらの変更により、net.go
にtimeoutError
に関するコードが追加されています。
変更の差分は以下の通りです。
diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go
index 5318c51c9a..bcd04a0ad8 100644
--- a/src/pkg/net/fd.go
+++ b/src/pkg/net/fd.go
@@ -377,14 +377,6 @@ func (fd *netFD) CloseWrite() error {
return fd.shutdown(syscall.SHUT_WR)
}
-type timeoutError struct{}
-
-func (e *timeoutError) Error() string { return "i/o timeout" }
-func (e *timeoutError) Timeout() bool { return true }
-func (e *timeoutError) Temporary() bool { return true }
-
-var errTimeout error = &timeoutError{}
-
func (fd *netFD) Read(p []byte) (n int, err error) {
if fd == nil {
return 0, os.EINVAL
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index 48f0ae791c..b236dfdb1d 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -157,6 +157,14 @@ func (e *OpError) Timeout() bool {
return ok && t.Timeout()\n }\n \n+type timeoutError struct{}\n+\n+func (e *timeoutError) Error() string { return "i/o timeout" }\n+func (e *timeoutError) Timeout() bool { return true }\n+func (e *timeoutError) Temporary() bool { return true }\n+\n+var errTimeout error = &timeoutError{}\n+\n type AddrError struct {\n \tErr string\n \tAddr string
コアとなるコードの解説
このコミットのコアとなる変更は、timeoutError
型とerrTimeout
変数の定義をfd.go
からnet.go
へ移動したことです。
-
fd.go
からの削除:fd.go
は、ファイルディスクリプタ(File Descriptor)を抽象化し、低レベルなI/O操作を扱うためのコードを含んでいます。このファイルはOS固有のコードを含むことがあり、特定のプラットフォームでのみコンパイルされる部分があるかもしれません。timeoutError
のような汎用的なエラー型がここに定義されていると、Windowsのような特定の環境でビルドする際に、その定義が他の部分から正しく参照できない、あるいはリンケージの問題を引き起こす可能性がありました。fd.go
からこの定義を削除することで、その問題を回避しています。 -
net.go
への追加:net.go
は、net
パッケージの主要な型、関数、変数などを定義する、より中心的なファイルです。このファイルにtimeoutError
を移動することで、以下の利点が得られます。- 可視性の向上:
net.go
に定義された型は、net
パッケージ内の他のすべてのファイルから、そしてnet
パッケージをインポートする外部のパッケージからも、一貫して参照可能になります。これにより、Windowsビルドにおけるシンボル解決の問題が解消されます。 - 適切な配置:
timeoutError
は、特定の低レベルなファイルディスクリプタ操作に限定されるエラーではなく、ネットワークI/O全般で発生しうる汎用的なタイムアウトエラーです。そのため、net
パッケージのコア定義を含むnet.go
に配置することが、論理的にも適切です。 - クロスプラットフォーム互換性: 汎用的なエラー型をOS固有の可能性のあるファイルから分離し、よりプラットフォームに依存しないコアファイルに置くことで、Goのクロスプラットフォームビルドの堅牢性が向上します。
- 可視性の向上:
この変更は、Go言語の初期段階におけるクロスプラットフォームビルドの課題と、パッケージ設計における適切な責務分担の重要性を示しています。
関連リンク
- Go CL 5505048: https://golang.org/cl/5505048
参考にした情報源リンク
- 特になし (コミットメッセージとGo言語の一般的な知識に基づいています)