[インデックス 11520] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージ内のDNSConfigError
型を、src/pkg/net/dnsconfig.go
からsrc/pkg/net/net.go
へ移動する変更を含んでいます。これにより、DNSConfigError
がWindows環境でも利用可能となり、net
パッケージのAPIシグネチャのプラットフォーム間の差異が解消されます。
コミット
net: move DNSConfigError to a portable file
The type being unavailable on Windows was the only API
signature difference in the net package.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5608043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/549ca930a068ebdf05133656ecde085368e18faa
元コミット内容
commit 549ca930a068ebdf05133656ecde085368e18faa
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Jan 31 13:01:34 2012 -0800
net: move DNSConfigError to a portable file
The type being unavailable on Windows was the only API
signature difference in the net package.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5608043
---
src/pkg/net/dnsconfig.go | 13 -------------\n src/pkg/net/net.go | 12 ++++++++++++\n 2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/src/pkg/net/dnsconfig.go b/src/pkg/net/dnsconfig.go
index c0ab80288d..bb46cc9007 100644
--- a/src/pkg/net/dnsconfig.go
+++ b/src/pkg/net/dnsconfig.go
@@ -17,19 +17,6 @@ type dnsConfig struct {
rotate bool // round robin among servers
}
-var dnsconfigError error
-
-type DNSConfigError struct {
- Err error
-}
-
-func (e *DNSConfigError) Error() string {
- return "error reading DNS config: " + e.Err.Error()
-}
-
-func (e *DNSConfigError) Timeout() bool { return false }
-func (e *DNSConfigError) Temporary() bool { return false }
-
// See resolv.conf(5) on a Linux machine.
// TODO(rsc): Supposed to call uname() and chop the beginning
// of the host name to get the default search domain.
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index 84cb4fcc73..79d36a2a81 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -201,3 +201,15 @@ type UnknownNetworkError string
func (e UnknownNetworkError) Error() string { return "unknown network " + string(e) }
func (e UnknownNetworkError) Temporary() bool { return false }
func (e UnknownNetworkError) Timeout() bool { return false }
+
+// DNSConfigError represents an error reading the machine's DNS configuration.
+type DNSConfigError struct {
+ Err error
+}
+
+func (e *DNSConfigError) Error() string {
+ return "error reading DNS config: " + e.Err.Error()
+}
+
+func (e *DNSConfigError) Timeout() bool { return false }
+func (e *DNSConfigError) Temporary() bool { return false }
変更の背景
このコミットの主な背景は、Go言語のnet
パッケージにおけるAPIシグネチャのプラットフォーム間の統一性を確保することにありました。以前は、DNSConfigError
型がWindows環境では利用できず、これがnet
パッケージのAPIにおいて唯一のプラットフォーム間の差異となっていました。
Go言語はクロスプラットフォーム開発を強く意識しており、可能な限りOSに依存しない一貫したAPIを提供することを目指しています。DNSConfigError
が特定のOS(この場合はWindows)でのみ利用できないという状況は、この設計思想に反していました。開発者が異なるOS上で同じGoのコードを記述する際に、APIの挙動が異なることは混乱を招き、コードの移植性を損なう可能性があります。
この問題を解決するため、DNSConfigError
をプラットフォームに依存しないファイルに移動することで、すべてのサポート対象OSでこの型が利用可能になり、net
パッケージのAPIが完全に統一されることになりました。これにより、Goのネットワーク関連コードのポータビリティと予測可能性が向上します。
前提知識の解説
Go言語のnet
パッケージ
Go言語の標準ライブラリであるnet
パッケージは、ネットワークI/Oの基本的な機能を提供します。TCP/IP、UDP、Unixドメインソケットなどのネットワークプロトコルを扱うためのインターフェースや、DNSルックアップ、IPアドレスの操作などの機能が含まれています。このパッケージは、Goアプリケーションがネットワーク通信を行う上で不可欠な基盤となります。
DNS (Domain Name System)
DNSは、インターネット上のコンピュータやサービスを識別するための分散型命名システムです。人間が覚えやすいドメイン名(例: example.com
)を、コンピュータが理解できるIPアドレス(例: 192.0.2.1
)に変換する役割を担っています。Goのnet
パッケージは、このDNSルックアップ機能を提供し、ホスト名からIPアドレスを解決したり、その逆を行ったりすることができます。
DNS設定ファイル
Unix系OS(Linux, macOSなど)では、DNSリゾルバの設定は通常/etc/resolv.conf
ファイルに記述されています。このファイルには、DNSサーバーのIPアドレスや検索ドメインなどが含まれます。Goのnet
パッケージは、システムがDNSルックアップを行う際に、この設定ファイルを読み取って利用します。
エラーハンドリングとerror
インターフェース
Go言語では、エラーは組み込みのerror
インターフェースによって表現されます。このインターフェースは、Error() string
という単一のメソッドを持ち、エラーメッセージを文字列として返します。Goの慣習として、関数は通常、最後の戻り値としてerror
型を返します。
さらに、Go 1.13以降では、エラーのラップ(fmt.Errorf
の%w
動詞)やアンラップ(errors.Unwrap
)、特定のエラー型との比較(errors.Is
)、特定のエラー型への変換(errors.As
)といった機能が導入され、より柔軟なエラーハンドリングが可能になっています。
net.Error
インターフェース
net
パッケージには、ネットワーク関連のエラーに特化したnet.Error
インターフェースが定義されています。このインターフェースは、標準のerror
インターフェースに加えて、以下の2つのメソッドを追加します。
Timeout() bool
: エラーがタイムアウトによるものかどうかを示す。Temporary() bool
: エラーが一時的なものであり、再試行によって解決する可能性があるかどうかを示す。
DNSConfigError
もこのnet.Error
インターフェースを実装しており、DNS設定の読み取りエラーが一時的なものではないこと(Temporary() false
)や、タイムアウトによるものではないこと(Timeout() false
)を示しています。
プラットフォーム依存のコード
Go言語では、ビルドタグ(build tags)やファイル名規則(例: _windows.go
, _linux.go
)を使用して、特定のOSやアーキテクチャに依存するコードを記述することができます。これにより、異なるプラットフォームで異なる実装を提供しつつ、共通のAPIを維持することが可能です。しかし、このコミットの背景にあるように、APIシグネチャ自体がプラットフォーム間で異なると、共通のコードを書くことが難しくなります。
技術的詳細
このコミットの技術的な核心は、DNSConfigError
というカスタムエラー型を、プラットフォーム固有のDNS設定を扱うファイル(src/pkg/net/dnsconfig.go
)から、より汎用的なネットワーク関連の型が定義されているファイル(src/pkg/net/net.go
)へ移動した点にあります。
src/pkg/net/dnsconfig.go
からの削除
元のsrc/pkg/net/dnsconfig.go
ファイルには、dnsConfig
構造体(DNS設定を保持)と、DNSConfigError
型が定義されていました。dnsconfig.go
は、主にUnix系システムにおける/etc/resolv.conf
のようなDNS設定ファイルの読み込みに関連するロジックを含んでいました。Windowsシステムでは、DNS設定の取得方法が異なるため、このファイル自体がビルドに含まれないか、あるいはその一部の機能が利用できない可能性がありました。
DNSConfigError
型がこのファイルに定義されていたため、Windows環境ではこの型がコンパイル時に存在しない、あるいは参照できないという問題が発生していました。これは、net
パッケージの他の部分がDNSConfigError
を参照しようとした際に、Windowsビルドでエラーとなるか、あるいはAPIのシグネチャがWindowsとUnix系OSで異なってしまう原因となっていました。
削除されたコードは以下の通りです。
var dnsconfigError error // この変数はDNSConfigError型とは直接関係ないが、同じファイルにあった
type DNSConfigError struct {
Err error
}
func (e *DNSConfigError) Error() string {
return "error reading DNS config: " + e.Err.Error()
}
func (e *DNSConfigError) Timeout() bool { return false }
func (e *DNSConfigError) Temporary() bool { return false }
src/pkg/net/net.go
への追加
src/pkg/net/net.go
は、net
パッケージの主要な型やインターフェース、汎用的なエラー型(例: UnknownNetworkError
)などが定義されているファイルです。このファイルは、Goがサポートするすべてのプラットフォームで共通してビルドされることが期待されます。
DNSConfigError
型をこのnet.go
ファイルに移動することで、このエラー型がどのプラットフォームでも常に利用可能になります。これにより、net
パッケージ内の他の関数やメソッドがDNSConfigError
を戻り値として返したり、引数として受け取ったりする際に、プラットフォーム間の差異を気にすることなく一貫したAPIシグネチャを維持できるようになります。
追加されたコードは以下の通りです。
// DNSConfigError represents an error reading the machine's DNS configuration.
type DNSConfigError struct {
Err error
}
func (e *DNSConfigError) Error() string {
return "error reading DNS config: " + e.Err.Error()
}
func (e *DNSConfigError) Timeout() bool { return false }
func (e *DNSConfigError) Temporary() bool { return false }
net.Error
インターフェースの実装
DNSConfigError
は、Error()
、Timeout()
、Temporary()
の3つのメソッドを実装しています。これは、Goのnet
パッケージで定義されているnet.Error
インターフェースの要件を満たしています。
Error() string
: エラーの文字列表現を返します。ここでは「error reading DNS config: [元のエラーメッセージ]」という形式です。Timeout() bool
: DNS設定の読み取りエラーは通常タイムアウトではないため、false
を返します。Temporary() bool
: DNS設定の読み取りエラーは通常一時的なものではなく、再試行で解決する可能性が低いため、false
を返します。
この移動により、net
パッケージ全体のAPIの一貫性が保たれ、特にクロスプラットフォーム開発において、開発者がより予測可能で安定したネットワーク関連の機能を利用できるようになりました。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更は、DNSConfigError
構造体とその関連メソッドの定義が、src/pkg/net/dnsconfig.go
からsrc/pkg/net/net.go
へ移動した点です。
src/pkg/net/dnsconfig.go
から削除された箇所:
--- a/src/pkg/net/dnsconfig.go
+++ b/src/pkg/net/dnsconfig.go
@@ -17,19 +17,6 @@ type dnsConfig struct {
rotate bool // round robin among servers
}
-var dnsconfigError error
-
-type DNSConfigError struct {
- Err error
-}
-
-func (e *DNSConfigError) Error() string {
- return "error reading DNS config: " + e.Err.Error()
-}
-
-func (e *DNSConfigError) Timeout() bool { return false }
-func (e *DNSConfigError) Temporary() bool { return false }
-
// See resolv.conf(5) on a Linux machine.
// TODO(rsc): Supposed to call uname() and chop the beginning
// of the host name to get the default search domain.
src/pkg/net/net.go
へ追加された箇所:
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -201,3 +201,15 @@ type UnknownNetworkError string
func (e UnknownNetworkError) Error() string { return "unknown network " + string(e) }
func (e UnknownNetworkError) Temporary() bool { return false }
func (e UnknownNetworkError) Timeout() bool { return false }
+
+// DNSConfigError represents an error reading the machine's DNS configuration.
+type DNSConfigError struct {
+ Err error
+}
+
+func (e *DNSConfigError) Error() string {
+ return "error reading DNS config: " + e.Err.Error()
+}
+
+func (e *DNSConfigError) Timeout() bool { return false }
+func (e *DNSConfigError) Temporary() bool { return false }
コアとなるコードの解説
DNSConfigError
は、Goのnet
パッケージにおいて、システムのDNS設定(例: /etc/resolv.conf
)を読み込む際に発生するエラーを表すカスタムエラー型です。この型は、Goのエラーハンドリングの慣習に従い、error
インターフェースを実装しています。
type DNSConfigError struct { Err error }
この行は、DNSConfigError
という新しい構造体を定義しています。この構造体は、Err
という名前のフィールドを一つ持ち、その型は組み込みのerror
インターフェースです。これにより、DNSConfigError
は、DNS設定の読み込み中に発生した具体的な下位のエラー(例えば、ファイルが見つからない、読み取り権限がないなど)を内部に保持することができます。
func (e *DNSConfigError) Error() string { return "error reading DNS config: " + e.Err.Error() }
これは、error
インターフェースのError()
メソッドの実装です。このメソッドは、エラーに関する人間が読める文字列を返します。DNSConfigError
の場合、"error reading DNS config: "という固定のプレフィックスに、内部に保持しているe.Err
(元のエラー)のError()
メソッドが返す文字列を連結して返します。これにより、ユーザーはDNS設定の読み込み中にエラーが発生したことと、その具体的な原因の両方を把握できます。
func (e *DNSConfigError) Timeout() bool { return false }
これは、net.Error
インターフェースのTimeout()
メソッドの実装です。このメソッドは、エラーがネットワーク操作のタイムアウトによって引き起こされた場合にtrue
を返します。DNS設定の読み込みは通常、ローカルファイルシステムからの操作であり、ネットワークタイムアウトとは直接関係がないため、このメソッドは常にfalse
を返します。
func (e *DNSConfigError) Temporary() bool { return false }
これは、net.Error
インターフェースのTemporary()
メソッドの実装です。このメソッドは、エラーが一時的なものであり、操作を再試行することで成功する可能性がある場合にtrue
を返します。DNS設定の読み込みエラーは、設定ファイルが存在しない、フォーマットが不正である、権限がないなど、永続的な問題に起因することが多いため、このメソッドは常にfalse
を返します。つまり、再試行しても同じエラーが発生する可能性が高いことを示唆しています。
これらのメソッドをnet.go
に移動することで、DNSConfigError
はGoがサポートするすべてのプラットフォームで一貫して利用可能なエラー型となり、net
パッケージのAPIの統一性とポータビリティが向上しました。
関連リンク
- Go CL 5608043: https://golang.org/cl/5608043
- Go
net
パッケージのドキュメント: https://pkg.go.dev/net - Go
error
インターフェースのドキュメント: https://pkg.go.dev/builtin#error
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード
- Go言語のエラーハンドリングに関する一般的な情報源
- DNSおよび
/etc/resolv.conf
に関する一般的な情報源 net.Error
インターフェースに関する情報源- Go言語のクロスプラットフォーム開発に関する情報源
- https://pkg.go.dev/net#Error (Go
net.Error
インターフェースの定義) - https://pkg.go.dev/net#DNSConfigError (Go
net.DNSConfigError
の現在の定義) - https://go.dev/blog/go1.13-errors (Go 1.13以降のエラーハンドリングに関するブログ記事)