[インデックス 10373] ファイルの概要
コミット
このコミットは、Windows環境におけるGoのsyscallパッケージのErrno
型に対してnet.Errorインターフェイスを実装するための修正です。具体的には、Temporary()
メソッドとTimeout()
メソッドを追加することで、ネットワークエラーハンドリングの一貫性を確保し、ビルドエラーを修正しています。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6677d2954eaa4d2ff89a5c962168440825b38611
元コミット内容
commit 6677d2954eaa4d2ff89a5c962168440825b38611
Author: Russ Cox <rsc@golang.org>
Date: Mon Nov 14 01:21:38 2011 -0500
syscall: make windows Errno implement net.Error (fix build)
TBR=brainman
CC=golang-dev
https://golang.org/cl/5371086
変更されたファイル:
src/pkg/syscall/dll_windows.go
: 8行の追加
追加されたメソッド:
func (e Errno) Temporary() bool {
return e == EINTR || e == EMFILE || e.Timeout()
}
func (e Errno) Timeout() bool {
return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
}
変更の背景
2011年当時のGo言語では、ネットワークプログラミングにおけるエラーハンドリングの統一性が重要な課題でした。特に、異なるオペレーティングシステム間でのエラー処理の一貫性を保つことが求められていました。
このコミットの背景には以下のような状況がありました:
-
クロスプラットフォーム対応の必要性: Go言語はクロスプラットフォーム対応を重視しており、UnixライクシステムとWindows間でのAPI互換性が重要でした。
-
ビルドエラーの発生: net.Errorインターフェイスを期待するコードがWindows環境で正しく動作しない状況が発生していました。
-
ネットワークエラーハンドリングの標準化: 一時的なエラー(リトライ可能)とタイムアウトエラーを区別することで、より堅牢なネットワークアプリケーションの開発が可能になります。
前提知識の解説
net.Errorインターフェイス
net.Errorは、Goの標準ライブラリにおけるネットワークエラーハンドリングの基盤となるインターフェイスです:
type Error interface {
error
Timeout() bool // エラーがタイムアウトによるものか?
Temporary() bool // エラーが一時的なものか?
}
このインターフェイスにより、クライアントコードは以下のような処理が可能になります:
if netErr, ok := err.(net.Error); ok {
if netErr.Temporary() {
// 一時的なエラー - リトライ可能
continue
}
if netErr.Timeout() {
// タイムアウトエラー - 適切な処理
return
}
}
syscallパッケージのErrno型
syscallパッケージのErrno型は、オペレーティングシステムのシステムコールから返されるエラーコードを表現します。Unix系システムでは標準的なerrno値を、WindowsではWindows APIのエラーコードをGo風にラップしています。
Windows特有のエラーコード
実装されたメソッドで使用されているエラーコードの意味:
- EINTR (Interrupted system call): システムコールが割り込みによって中断された
- EMFILE (Too many open files): プロセスが開けるファイル数の上限に達した
- EAGAIN (Resource temporarily unavailable): リソースが一時的に利用できない
- EWOULDBLOCK (Operation would block): ノンブロッキング操作がブロックする状況
- ETIMEDOUT (Connection timed out): 接続がタイムアウトした
技術的詳細
Temporary()メソッドの実装
func (e Errno) Temporary() bool {
return e == EINTR || e == EMFILE || e.Timeout()
}
このメソッドは以下の条件でtrueを返します:
- EINTR: システムコールが割り込まれた場合。これは通常リトライ可能な状況です。
- EMFILE: ファイルディスクリプタの上限に達した場合。アプリケーションが適切にリソース管理を行えばリトライ可能です。
- Timeout()がtrue: タイムアウトエラーも一般的に一時的なものとして扱われます。
Timeout()メソッドの実装
func (e Errno) Timeout() bool {
return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
}
このメソッドは以下のエラーコードでtrueを返します:
- EAGAIN: リソースが一時的に利用できない状態
- EWOULDBLOCK: ノンブロッキング操作がブロックする状況
- ETIMEDOUT: 明示的なタイムアウト
設計上の考慮点
-
相互依存関係:
Temporary()
がTimeout()
を呼び出す設計により、タイムアウトエラーは常に一時的なエラーとしても扱われます。 -
Windows固有の対応: Windows環境でのエラーコードをUnix風のerrno値にマッピングし、クロスプラットフォーム互換性を実現しています。
-
最小限の実装: 必要最小限のエラーコードのみを対象とし、シンプルな実装を保っています。
コアとなるコードの変更箇所
変更はsrc/pkg/syscall/dll_windows.go
ファイルの1箇所のみです:
@@ -15,6 +15,14 @@ func (e Errno) Error() string {
return errstr(e)
}
+func (e Errno) Temporary() bool {
+ return e == EINTR || e == EMFILE || e.Timeout()
+}
+
+func (e Errno) Timeout() bool {
+ return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
+}
+
// DLLError describes reasons for DLL load failures.
type DLLError struct {
Err error
コアとなるコードの解説
メソッドの配置
新しいメソッドは既存のError()
メソッドの直後、DLLError
構造体の定義の前に配置されています。これにより、Errno型に関連するすべてのメソッドが論理的にグループ化されています。
エラー分類の論理
実装されたロジックは以下の階層構造を持ちます:
Temporary() = EINTR || EMFILE || Timeout()
Timeout() = EAGAIN || EWOULDBLOCK || ETIMEDOUT
この設計により:
- すべてのタイムアウトエラーは一時的エラーとしても扱われる
- システム割り込み(EINTR)とリソース不足(EMFILE)も一時的エラーとして扱われる
- 明確な分類により、適切なエラーハンドリング戦略を選択可能
Windows環境での意義
Windows環境において、これらのPOSIX風エラーコードを使用することで:
- プラットフォーム抽象化: Unix系とWindows系で統一されたエラーハンドリング
- 既存コードとの互換性: net.Errorインターフェイスを期待するコードとの互換性
- 開発者体験の向上: プラットフォーム固有のエラーハンドリングコードの削減
関連リンク
- Go net package documentation
- Go syscall package documentation
- net.Error interface definition
- Original Gerrit Code Review
参考にした情報源リンク
- Go Issue #45729: net: deprecate Temporary error status
- Go Issue #48268: net: document the meaning of "Temporary" and "Timeout"
- Go Issue #15637: syscall: Windows Errno.Temporary and Errno.Timeout are incomplete
- Cloudflare Blog: The complete guide to Go net/http timeouts
- Go Blog: Error handling and Go
- Go Source: syscall package Windows implementation