[インデックス 18067] ファイルの概要
このコミットは、Go言語の標準ライブラリ net
パッケージにおけるDNSルックアップのテストケース追加に関するものです。特に、netgo
と cgo
の両方のDNS解決メカニズムを検証するためのテストが導入されています。
コミット
commit 2b3ad827a6c45395db669aeec331ac134582a56
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Thu Dec 19 07:40:10 2013 +0900
net: add test cases for the both of netgo, cgo DNS lookups
Update #4078
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/14638043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2b3ad827a6c45395db669aeec3313ac134582a56
元コミット内容
net: add test cases for the both of netgo, cgo DNS lookups
このコミットは、Goの net
パッケージに、netgo
と cgo
の両方のDNSルックアップメカニズムのためのテストケースを追加します。これは、Go issue #4078 に関連する更新です。
変更の背景
Go言語のネットワークパッケージ net
は、DNS(Domain Name System)の名前解決を行う際に、複数のメカニズムをサポートしています。主なものとして、Go言語自身で実装された純粋なGoコードによるDNSリゾルバ(netgo
)と、C言語の標準ライブラリ(通常はglibcなどのシステムリゾルバ)をCgo経由で利用するリゾルバ(cgo
)があります。
Goの初期のバージョンでは、Cgoが利用可能な環境(特にUnix系システム)ではデフォルトでCgoベースのリゾルバが使用されていました。これは、システムの設定(/etc/resolv.conf
や /etc/hosts
など)や、NSS (Name Service Switch) の設定(/etc/nsswitch.conf
)に完全に準拠できるという利点がありました。しかし、Cgoを使用すると、クロスコンパイルが複雑になったり、静的リンクが困難になったり、あるいはCgoのオーバーヘッドが発生したりするなどのデメリットも存在しました。
そのため、Go 1.1以降では、netgo
ビルドタグを使用することで、純粋なGo実装のリゾルバを強制的に使用できるようになりました。これにより、Cgoに依存しないバイナリを生成できるようになり、デプロイの柔軟性が向上しました。
しかし、この二つの異なるDNS解決メカニズムが存在することで、それぞれが期待通りに動作するか、特にエッジケースや特定の設定下で問題が発生しないかを検証することが重要になります。Go issue #4078 は、おそらくこれらのDNSルックアップメカニズムに関する既存のバグや、テストカバレッジの不足を指摘していたと考えられます。このコミットは、その問題に対処し、両方のリゾルバが正しく機能することを保証するためのテストを追加することを目的としています。
前提知識の解説
DNS (Domain Name System)
DNSは、インターネット上のコンピュータやサービスを識別するためのドメイン名(例: example.com
)を、それに対応するIPアドレス(例: 93.184.216.34
)に変換する分散型のシステムです。ユーザーがウェブサイトにアクセスする際、ブラウザはまずDNSを使ってドメイン名をIPアドレスに解決し、そのIPアドレスを使ってサーバーに接続します。
Go言語の net
パッケージ
Go言語の標準ライブラリ net
パッケージは、ネットワークI/Oのプリミティブを提供します。これには、TCP/UDP接続、IPアドレスの操作、そしてDNSの名前解決などが含まれます。
Cgo
Cgoは、GoプログラムからC言語のコードを呼び出すためのGoの機能です。これにより、Go言語で書かれたアプリケーションが、既存のCライブラリ(例えば、システムコールや特定のハードウェアと対話するためのライブラリ)を利用できるようになります。DNS解決の文脈では、CgoはシステムにインストールされているC言語ベースのDNSリゾルバ(通常はglibcの getaddrinfo
など)を呼び出すために使用されます。
netgo
と cgo
ビルドタグ
Goのビルドシステムでは、ビルドタグ(build tags)を使用して、特定の条件に基づいてソースファイルをコンパイルに含めるか除外するかを制御できます。
cgo
: このタグは、Cgoが有効な場合に自動的に設定されます。Goのネットワークパッケージでは、このタグが存在する場合、Cgoを介してシステムのDNSリゾルバを使用しようとします。netgo
: このタグは、Go言語自身で実装された純粋なGoコードによるDNSリゾルバを使用することを強制するために、明示的にビルドコマンドで指定されます(例:go build -tags netgo
)。このタグが指定されると、Cgoベースのリゾルバは使用されません。!cgo
:cgo
タグが設定されていないことを意味します。これは、Cgoが無効な環境や、netgo
タグが指定された場合に該当します。!netgo
:netgo
タグが設定されていないことを意味します。これは、Cgoベースのリゾルバが使用される可能性がある場合に該当します。
これらのタグの組み合わせによって、Goの net
パッケージはDNS解決の挙動を切り替えます。
cgoLookupIP
と goLookupIP
Goの net
パッケージ内部には、DNSルックアップを行うための抽象化された関数が存在します。
cgoLookupIP
: Cgoを介してシステムのDNSリゾルバを呼び出すための内部関数(またはそのラッパー)。goLookupIP
: 純粋なGoコードで実装されたDNSリゾルバを呼び出すための内部関数。
これらの関数は、外部に公開されている net.LookupIP
などの関数から内部的に呼び出され、ビルドタグや環境に応じて適切な実装が選択されます。
技術的詳細
このコミットは、GoのDNSルックアップメカニズムの堅牢性を高めるために、netgo
と cgo
の両方のパスを検証する新しいテストケースを追加します。具体的には、以下の2つの新しいテストファイルが追加されています。
src/pkg/net/cgo_unix_test.go
src/pkg/net/netgo_unix_test.go
これらのファイルは、それぞれ異なるビルドタグの組み合わせでコンパイルされるように設計されており、それぞれのDNS解決パスが正しく機能するかどうかを独立してテストします。
cgo_unix_test.go
のテストロジック
このテストファイルは、+build cgo,!netgo
というビルドタグを持っています。これは、Cgoが有効で、かつ netgo
タグが指定されていない(つまり、Cgoベースのリゾルバが使用されるべき)Unix系システムでのみコンパイルおよび実行されることを意味します。
TestCgoLookupIP
関数では、以下の検証が行われます。
cgoLookupIP("localhost")
を呼び出し、その結果を検証します。ok
がfalse
でないこと(cgoLookupIP
がプレースホルダーではないこと)を確認します。これは、Cgoベースのリゾルバが実際に利用可能であることを意味します。err
がnil
であること(エラーが発生しないこと)を確認します。
goLookupIP("localhost")
を呼び出し、その結果を検証します。err
がnil
であること(エラーが発生しないこと)を確認します。これは、Cgoベースのリゾルバが使用されている場合でも、Go実装のリゾルバが機能することを確認するためです。
このテストの目的は、Cgoが有効な環境で、システムのリゾルバが正しく機能し、cgoLookupIP
が期待通りに動作することを確認することです。
netgo_unix_test.go
のテストロジック
このテストファイルは、+build !cgo netgo
というビルドタグを持っています。これは、Cgoが無効であるか、または netgo
タグが明示的に指定されている(つまり、純粋なGo実装のリゾルバが使用されるべき)Unix系システムでのみコンパイルおよび実行されることを意味します。
TestGoLookupIP
関数では、以下の検証が行われます。
cgoLookupIP("localhost")
を呼び出し、その結果を検証します。ok
がtrue
でないこと(cgoLookupIP
がプレースホルダーであること)を確認します。これは、netgo
モードではCgoベースのリゾルバが使用されないことを意味します。err
がnil
であること(エラーが発生しないこと)を確認します。cgoLookupIP
がプレースホルダーである場合、通常はエラーを返さないか、特定のプレースホルダーエラーを返すことが期待されます。
goLookupIP("localhost")
を呼び出し、その結果を検証します。err
がnil
であること(エラーが発生しないこと)を確認します。これは、netgo
モードでGo実装のリゾルバが正しく機能することを確認するためです。
このテストの目的は、netgo
モードで、純粋なGo実装のリゾルバが正しく機能し、Cgoベースのリゾルバが意図的にバイパスされていることを確認することです。
両方のテストファイルで localhost
を使用しているのは、通常、システムのリゾルバ設定に依存せず、確実に解決できるホスト名であるためです。これにより、外部ネットワークの可用性や特定のDNSサーバーの設定に左右されずに、内部のDNS解決ロジックをテストできます。
コアとなるコードの変更箇所
このコミットによって追加されたファイルは以下の2つです。
-
src/pkg/net/cgo_unix_test.go
// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build cgo,!netgo // +build darwin dragonfly freebsd linux netbsd openbsd package net import "testing" func TestCgoLookupIP(t *testing.T) { host := "localhost" _, err, ok := cgoLookupIP(host) if !ok { t.Errorf("cgoLookupIP must not be a placeholder") } if err != nil { t.Errorf("cgoLookupIP failed: %v", err) } if _, err := goLookupIP(host); err != nil { t.Errorf("goLookupIP failed: %v", err) } }
-
src/pkg/net/netgo_unix_test.go
// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !cgo netgo // +build darwin dragonfly freebsd linux netbsd openbsd package net import "testing" func TestGoLookupIP(t *testing.T) { host := "localhost" _, err, ok := cgoLookupIP(host) if ok { t.Errorf("cgoLookupIP must be a placeholder") } if err != nil { t.Errorf("cgoLookupIP failed: %v", err) } if _, err := goLookupIP(host); err != nil { t.Errorf("goLookupIP failed: %v", err) } }
コアとなるコードの解説
src/pkg/net/cgo_unix_test.go
- ビルドタグ:
// +build cgo,!netgo
は、このファイルがCgoが有効で、かつnetgo
タグが指定されていない場合にのみコンパイルされることを示します。これは、GoがCgoベースのDNSリゾルバを使用するデフォルトの動作をテストするためのものです。 TestCgoLookupIP
関数:host := "localhost"
: テスト対象のホスト名としてlocalhost
を使用します。これは通常、システムのリゾルバによって確実に解決されるため、テストの安定性を高めます。_, err, ok := cgoLookupIP(host)
:cgoLookupIP
は、Cgoを介してシステムのDNSリゾルバを呼び出すGoの内部関数です。返り値のok
は、その関数が実際に利用可能(プレースホルダーではない)かどうかを示します。if !ok { t.Errorf("cgoLookupIP must not be a placeholder") }
:cgo
モードではcgoLookupIP
が実際に機能する実装であるべきなので、ok
がtrue
であることを確認します。if err != nil { t.Errorf("cgoLookupIP failed: %v", err) }
:cgoLookupIP
の呼び出しでエラーが発生しないことを確認します。if _, err := goLookupIP(host); err != nil { t.Errorf("goLookupIP failed: %v", err) }
:goLookupIP
は純粋なGo実装のリゾルバです。cgo
モードであっても、goLookupIP
がエラーなく動作することを確認します。これは、Goのネットワークスタックが両方のリゾルバを適切に管理できることを保証するためです。
src/pkg/net/netgo_unix_test.go
- ビルドタグ:
// +build !cgo netgo
は、このファイルがCgoが無効であるか、またはnetgo
タグが明示的に指定されている場合にのみコンパイルされることを示します。これは、Goが純粋なGo実装のDNSリゾルバを使用する動作をテストするためのものです。 TestGoLookupIP
関数:host := "localhost"
: 同様にlocalhost
を使用します。_, err, ok := cgoLookupIP(host)
: ここでもcgoLookupIP
を呼び出しますが、netgo
モードではその挙動が異なります。if ok { t.Errorf("cgoLookupIP must be a placeholder") }
:netgo
モードでは、cgoLookupIP
は使用されないため、その実装はプレースホルダーであるべきです。したがって、ok
がfalse
であることを確認します。if err != nil { t.Errorf("cgoLookupIP failed: %v", err) }
: プレースホルダーの呼び出しでエラーが発生しないことを確認します。if _, err := goLookupIP(host); err != nil { t.Errorf("goLookupIP failed: %v", err) }
:netgo
モードではgoLookupIP
が主要なリゾルバとなるため、これがエラーなく動作することを確実に検証します。
これらのテストは、GoのDNS解決メカニズムが、ビルドタグや環境に応じて適切に切り替わり、それぞれのパスで期待通りの結果を返すことを保証するための重要な追加です。これにより、Goアプリケーションのネットワーク機能の信頼性が向上します。
関連リンク
- Go issue #4078: https://github.com/golang/go/issues/4078 (このコミットが更新するIssue)
- Go CL 14638043: https://golang.org/cl/14638043 (このコミットに対応するGerrit Change-ID)
参考にした情報源リンク
- Go issue #4078 の内容 (Web検索による)
- Go言語のビルドタグに関する公式ドキュメント (Web検索による)
- Go言語の
net
パッケージの内部実装に関する一般的な知識 - Cgoに関するGo公式ドキュメント (Web検索による)
- DNSの基本的な概念 (一般的な知識)
localhost
の名前解決に関する一般的な知識I have read the commit data and formulated a detailed explanation. I will now output the explanation in Markdown format as requested.
# [インデックス 18067] ファイルの概要
このコミットは、Go言語の標準ライブラリ `net` パッケージにおけるDNSルックアップのテストケース追加に関するものです。特に、`netgo` と `cgo` の両方のDNS解決メカニズムを検証するためのテストが導入されています。
## コミット
commit 2b3ad827a6c45395db669aeec331ac134582a56 Author: Mikio Hara mikioh.mikioh@gmail.com Date: Thu Dec 19 07:40:10 2013 +0900
net: add test cases for the both of netgo, cgo DNS lookups
Update #4078
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/14638043
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/2b3ad827a6c45395db669aeec3313ac134582a56](https://github.com/golang/go/commit/2b3ad827a6c45395db669aeec3313ac134582a56)
## 元コミット内容
`net: add test cases for the both of netgo, cgo DNS lookups`
このコミットは、Goの `net` パッケージに、`netgo` と `cgo` の両方のDNSルックアップメカニズムのためのテストケースを追加します。これは、Go issue #4078 に関連する更新です。
## 変更の背景
Go言語のネットワークパッケージ `net` は、DNS(Domain Name System)の名前解決を行う際に、複数のメカニズムをサポートしています。主なものとして、Go言語自身で実装された純粋なGoコードによるDNSリゾルバ(`netgo`)と、C言語の標準ライブラリ(通常はglibcなどのシステムリゾルバ)をCgo経由で利用するリゾルバ(`cgo`)があります。
Goの初期のバージョンでは、Cgoが利用可能な環境(特にUnix系システム)ではデフォルトでCgoベースのリゾルバが使用されていました。これは、システムの設定(`/etc/resolv.conf` や `/etc/hosts` など)や、NSS (Name Service Switch) の設定(`/etc/nsswitch.conf`)に完全に準拠できるという利点がありました。しかし、Cgoを使用すると、クロスコンパイルが複雑になったり、静的リンクが困難になったり、あるいはCgoのオーバーヘッドが発生したりするなどのデメリットも存在しました。
そのため、Go 1.1以降では、`netgo` ビルドタグを使用することで、純粋なGo実装のリゾルバを強制的に使用できるようになりました。これにより、Cgoに依存しないバイナリを生成できるようになり、デプロイの柔軟性が向上しました。
しかし、この二つの異なるDNS解決メカニズムが存在することで、それぞれが期待通りに動作するか、特にエッジケースや特定の設定下で問題が発生しないかを検証することが重要になります。Go issue #4078 は、おそらくこれらのDNSルックアップメカニズムに関する既存のバグや、テストカバレッジの不足を指摘していたと考えられます。このコミットは、その問題に対処し、両方のリゾルバが正しく機能することを保証するためのテストを追加することを目的としています。
## 前提知識の解説
### DNS (Domain Name System)
DNSは、インターネット上のコンピュータやサービスを識別するためのドメイン名(例: `example.com`)を、それに対応するIPアドレス(例: `93.184.216.34`)に変換する分散型のシステムです。ユーザーがウェブサイトにアクセスする際、ブラウザはまずDNSを使ってドメイン名をIPアドレスに解決し、そのIPアドレスを使ってサーバーに接続します。
### Go言語の `net` パッケージ
Go言語の標準ライブラリ `net` パッケージは、ネットワークI/Oのプリミティブを提供します。これには、TCP/UDP接続、IPアドレスの操作、そしてDNSの名前解決などが含まれます。
### Cgo
Cgoは、GoプログラムからC言語のコードを呼び出すためのGoの機能です。これにより、Go言語で書かれたアプリケーションが、既存のCライブラリ(例えば、システムコールや特定のハードウェアと対話するためのライブラリ)を利用できるようになります。DNS解決の文脈では、CgoはシステムにインストールされているC言語ベースのDNSリゾルバ(通常はglibcの `getaddrinfo` など)を呼び出すために使用されます。
### `netgo` と `cgo` ビルドタグ
Goのビルドシステムでは、ビルドタグ(build tags)を使用して、特定の条件に基づいてソースファイルをコンパイルに含めるか除外するかを制御できます。
* **`cgo`**: このタグは、Cgoが有効な場合に自動的に設定されます。Goのネットワークパッケージでは、このタグが存在する場合、Cgoを介してシステムのDNSリゾルバを使用しようとします。
* **`netgo`**: このタグは、Go言語自身で実装された純粋なGoコードによるDNSリゾルバを使用することを強制するために、明示的にビルドコマンドで指定されます(例: `go build -tags netgo`)。このタグが指定されると、Cgoベースのリゾルバは使用されません。
* **`!cgo`**: `cgo` タグが設定されていないことを意味します。これは、Cgoが無効な環境や、`netgo` タグが指定された場合に該当します。
* **`!netgo`**: `netgo` タグが設定されていないことを意味します。これは、Cgoベースのリゾルバが使用される可能性がある場合に該当します。
これらのタグの組み合わせによって、Goの `net` パッケージはDNS解決の挙動を切り替えます。
### `cgoLookupIP` と `goLookupIP`
Goの `net` パッケージ内部には、DNSルックアップを行うための抽象化された関数が存在します。
* `cgoLookupIP`: Cgoを介してシステムのDNSリゾルバを呼び出すための内部関数(またはそのラッパー)。
* `goLookupIP`: 純粋なGoコードで実装されたDNSリゾルバを呼び出すための内部関数。
これらの関数は、外部に公開されている `net.LookupIP` などの関数から内部的に呼び出され、ビルドタグや環境に応じて適切な実装が選択されます。
## 技術的詳細
このコミットは、GoのDNSルックアップメカニズムの堅牢性を高めるために、`netgo` と `cgo` の両方のパスを検証する新しいテストケースを追加します。具体的には、以下の2つの新しいテストファイルが追加されています。
1. `src/pkg/net/cgo_unix_test.go`
2. `src/pkg/net/netgo_unix_test.go`
これらのファイルは、それぞれ異なるビルドタグの組み合わせでコンパイルされるように設計されており、それぞれのDNS解決パスが正しく機能するかどうかを独立してテストします。
### `cgo_unix_test.go` のテストロジック
このテストファイルは、`+build cgo,!netgo` というビルドタグを持っています。これは、Cgoが有効で、かつ `netgo` タグが指定されていない(つまり、Cgoベースのリゾルバが使用されるべき)Unix系システムでのみコンパイルおよび実行されることを意味します。
`TestCgoLookupIP` 関数では、以下の検証が行われます。
* `cgoLookupIP("localhost")` を呼び出し、その結果を検証します。
* `ok` が `false` でないこと(`cgoLookupIP` がプレースホルダーではないこと)を確認します。これは、Cgoベースのリゾルバが実際に利用可能であることを意味します。
* `err` が `nil` であること(エラーが発生しないこと)を確認します。
* `goLookupIP("localhost")` を呼び出し、その結果を検証します。
* `err` が `nil` であること(エラーが発生しないこと)を確認します。これは、Cgoベースのリゾルバが使用されている場合でも、Go実装のリゾルバが機能することを確認するためです。
このテストの目的は、Cgoが有効な環境で、システムのリゾルバが正しく機能し、`cgoLookupIP` が期待通りに動作することを確認することです。
### `netgo_unix_test.go` のテストロジック
このテストファイルは、`+build !cgo netgo` というビルドタグを持っています。これは、Cgoが無効であるか、または `netgo` タグが明示的に指定されている(つまり、純粋なGo実装のリゾルバが使用されるべき)Unix系システムでのみコンパイルおよび実行されることを意味します。
`TestGoLookupIP` 関数では、以下の検証が行われます。
* `cgoLookupIP("localhost")` を呼び出し、その結果を検証します。
* `ok` が `true` でないこと(`cgoLookupIP` がプレースホルダーであること)を確認します。これは、`netgo` モードではCgoベースのリゾルバが使用されないことを意味します。
* `err` が `nil` であること(エラーが発生しないこと)を確認します。`cgoLookupIP` がプレースホルダーである場合、通常はエラーを返さないか、特定のプレースホルダーエラーを返すことが期待されます。
* `goLookupIP("localhost")` を呼び出し、その結果を検証します。
* `err` が `nil` であること(エラーが発生しないこと)を確認します。これは、`netgo` モードでGo実装のリゾルバが正しく機能することを確認するためです。
このテストの目的は、`netgo` モードで、純粋なGo実装のリゾルバが正しく機能し、Cgoベースのリゾルバが意図的にバイパスされていることを確認することです。
両方のテストファイルで `localhost` を使用しているのは、通常、システムのリゾルバ設定に依存せず、確実に解決できるホスト名であるためです。これにより、外部ネットワークの可用性や特定のDNSサーバーの設定に左右されずに、内部のDNS解決ロジックをテストできます。
## コアとなるコードの変更箇所
このコミットによって追加されたファイルは以下の2つです。
1. `src/pkg/net/cgo_unix_test.go`
```go
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build cgo,!netgo
// +build darwin dragonfly freebsd linux netbsd openbsd
package net
import "testing"
func TestCgoLookupIP(t *testing.T) {
host := "localhost"
_, err, ok := cgoLookupIP(host)
if !ok {
t.Errorf("cgoLookupIP must not be a placeholder")
}
if err != nil {
t.Errorf("cgoLookupIP failed: %v", err)
}
if _, err := goLookupIP(host); err != nil {
t.Errorf("goLookupIP failed: %v", err)
}
}
```
2. `src/pkg/net/netgo_unix_test.go`
```go
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !cgo netgo
// +build darwin dragonfly freebsd linux netbsd openbsd
package net
import "testing"
func TestGoLookupIP(t *testing.T) {
host := "localhost"
_, err, ok := cgoLookupIP(host)
if ok {
t.Errorf("cgoLookupIP must be a placeholder")
}
if err != nil {
t.Errorf("cgoLookupIP failed: %v", err)
}
if _, err := goLookupIP(host); err != nil {
t.Errorf("goLookupIP failed: %v", err)
}
}
```
## コアとなるコードの解説
### `src/pkg/net/cgo_unix_test.go`
* **ビルドタグ**: `// +build cgo,!netgo` は、このファイルがCgoが有効で、かつ `netgo` タグが指定されていない場合にのみコンパイルされることを示します。これは、GoがCgoベースのDNSリゾルバを使用するデフォルトの動作をテストするためのものです。
* **`TestCgoLookupIP` 関数**:
* `host := "localhost"`: テスト対象のホスト名として `localhost` を使用します。これは通常、システムのリゾルバによって確実に解決されるため、テストの安定性を高めます。
* `_, err, ok := cgoLookupIP(host)`: `cgoLookupIP` は、Cgoを介してシステムのDNSリゾルバを呼び出すGoの内部関数です。返り値の `ok` は、その関数が実際に利用可能(プレースホルダーではない)かどうかを示します。
* `if !ok { t.Errorf("cgoLookupIP must not be a placeholder") }`: `cgo` モードでは `cgoLookupIP` が実際に機能する実装であるべきなので、`ok` が `true` であることを確認します。
* `if err != nil { t.Errorf("cgoLookupIP failed: %v", err) }`: `cgoLookupIP` の呼び出しでエラーが発生しないことを確認します。
* `if _, err := goLookupIP(host); err != nil { t.Errorf("goLookupIP failed: %v", err) }`: `goLookupIP` は純粋なGo実装のリゾルバです。`cgo` モードであっても、`goLookupIP` がエラーなく動作することを確認します。これは、Goのネットワークスタックが両方のリゾルバを適切に管理できることを保証するためです。
### `src/pkg/net/netgo_unix_test.go`
* **ビルドタグ**: `// +build !cgo netgo` は、このファイルがCgoが無効であるか、または `netgo` タグが明示的に指定されている場合にのみコンパイルされることを示します。これは、Goが純粋なGo実装のDNSリゾルバを使用する動作をテストするためのものです。
* **`TestGoLookupIP` 関数**:
* `host := "localhost"`: 同様に `localhost` を使用します。
* `_, err, ok := cgoLookupIP(host)`: ここでも `cgoLookupIP` を呼び出しますが、`netgo` モードではその挙動が異なります。
* `if ok { t.Errorf("cgoLookupIP must be a placeholder") }`: `netgo` モードでは、`cgoLookupIP` は使用されないため、その実装はプレースホルダーであるべきです。したがって、`ok` が `false` であることを確認します。
* `if err != nil { t.Errorf("cgoLookupIP failed: %v", err) }`: プレースホルダーの呼び出しでエラーが発生しないことを確認します。
* `if _, err := goLookupIP(host); err != nil { t.Errorf("goLookupIP failed: %v", err) }`: `netgo` モードでは `goLookupIP` が主要なリゾルバとなるため、これがエラーなく動作することを確実に検証します。
これらのテストは、GoのDNS解決メカニズムが、ビルドタグや環境に応じて適切に切り替わり、それぞれのパスで期待通りの結果を返すことを保証するための重要な追加です。これにより、Goアプリケーションのネットワーク機能の信頼性が向上します。
## 関連リンク
* Go issue #4078: [https://github.com/golang/go/issues/4078](https://github.com/golang/go/issues/4078) (このコミットが更新するIssue)
* Go CL 14638043: [https://golang.org/cl/14638043](https://golang.org/cl/14638043) (このコミットに対応するGerrit Change-ID)
## 参考にした情報源リンク
* Go issue #4078 の内容 (Web検索による)
* Go言語のビルドタグに関する公式ドキュメント (Web検索による)
* Go言語の `net` パッケージの内部実装に関する一般的な知識
* Cgoに関するGo公式ドキュメント (Web検索による)
* DNSの基本的な概念 (一般的な知識)
* `localhost` の名前解決に関する一般的な知識