[インデックス 19239] ファイルの概要
このコミットは、Go言語の標準ライブラリnet/http/httputil
パッケージ内のClientConn
およびServerConn
型について、その使用を非推奨とし、代わりにnet/http
パッケージのClient
およびServer
型を使用するよう開発者に促すためのドキュメント変更を導入するものです。具体的には、これらの低レベルAPIのGo 1リリースへの誤った含まれ方と、その後のメンテナンス不足、そしてnet/http
パッケージ自体がこれらを使用していないという事実を背景に、誤用を防ぐための警告コメントが追加されました。
コミット
- コミットハッシュ:
9f2e1efd725036c2d71a5d5df39ffe42b12e9383
- Author: Brad Fitzpatrick bradfitz@golang.org
- Date: Sat Apr 26 22:14:39 2014 -0700
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9f2e1efd725036c2d71a5d5df39ffe42b12e9383
元コミット内容
net/http/httputil: tell people not to use ClientConn and ServerConn
A very smart developer at Gophercon just asked me to help debug
a problem and I was horrified to learn that he was using httputil's
ClientConn. I forgot ClientConn and ServerConn were even included
in Go 1! They should've been deleted.
Scare people away from using them. The net/http package does
not use them and they're unused, unmaintained and untouched in
4+ years.
LGTM=r
R=r, adg
CC=golang-codereviews
https://golang.org/cl/92790043
変更の背景
このコミットの背景には、net/http/httputil
パッケージに含まれるClientConn
とServerConn
という低レベルなHTTPコネクション管理APIが、Go 1のリリース時に意図せず含まれてしまい、その後もメンテナンスされずに放置されていたという問題があります。
コミットメッセージによると、Gopherconで一人の開発者がhttputil.ClientConn
を使用している問題のデバッグを手伝った際に、コミッターであるBrad Fitzpatrick氏がこれらのAPIがGo 1に存在することに驚愕したと述べています。これらのAPIは、net/http
パッケージのより高レベルなClient
やServer
型とは異なり、Goの標準HTTPスタックでは内部的に使用されておらず、4年以上も手つかずのままでした。
このような状況は、開発者が意図しない低レベルAPIを使用してしまい、予期せぬ問題や将来的な互換性の問題に直面するリスクをはらんでいました。そのため、これらのAPIの使用を積極的に discourage (推奨しない) し、より適切でメンテナンスされたnet/http
パッケージのAPIへの移行を促す必要がありました。このコミットは、その目的のためにドキュメントに警告を追加することで、開発者への明確なガイダンスを提供することを意図しています。
前提知識の解説
このコミットを理解するためには、Go言語のnet/http
パッケージと、net/http/httputil
パッケージの役割、そしてHTTPプロトコルにおけるコネクション管理の基本的な概念を理解しておく必要があります。
-
net/http
パッケージ: Go言語の標準ライブラリで、HTTPクライアントとサーバーの実装を提供します。http.Server
: HTTPリクエストを処理するためのサーバー機能を提供します。通常、http.ListenAndServe
関数を通じて利用され、リクエストのルーティング、ハンドリング、レスポンスの送信など、高レベルなサーバー機能を提供します。http.Client
: HTTPリクエストを送信するためのクライアント機能を提供します。http.Get
やhttp.Post
などの便利な関数を通じて利用され、コネクションの再利用、リダイレクトの処理、タイムアウト設定など、高レベルなクライアント機能を提供します。- コネクション管理:
http.Client
やhttp.Server
は、内部的にHTTP/1.1の永続的コネクション(Keep-Alive)やコネクションプーリングなどを自動的に処理し、効率的な通信を実現します。開発者は通常、これらの低レベルなコネクション管理の詳細を意識する必要はありません。
-
net/http/httputil
パッケージ:net/http
パッケージを補完するユーティリティ機能を提供します。これには、リバースプロキシ、ダンプ機能、そして本コミットの対象であるClientConn
とServerConn
のような低レベルなコネクション管理プリミティブが含まれていました。httputil.ClientConn
: HTTPクライアント側で、単一のTCPコネクション上でHTTPリクエストとレスポンスを低レベルでやり取りするための構造体です。これは、net.Conn
をラップし、リクエストの書き込みとレスポンスの読み込みを直接制御することを目的としていました。httputil.ServerConn
: HTTPサーバー側で、単一のTCPコネクション上でHTTPリクエストとレスポンスを低レベルでやり取りするための構造体です。こちらもnet.Conn
をラップし、リクエストの読み込みとレスポンスの書き込みを直接制御することを目的としていました。
-
低レベルAPIと高レベルAPI: ソフトウェア開発において、APIは通常、低レベルなものと高レベルなものに分類されます。
- 低レベルAPI: ハードウェアやOSの機能に直接アクセスするなど、より細かい制御を可能にするが、使用が複雑で、誤用すると問題を引き起こしやすい傾向があります。
- 高レベルAPI: 低レベルAPIの上に構築され、より抽象化された機能を提供します。使用が簡単で、一般的なユースケースに適していますが、細かい制御は制限される場合があります。
httputil.ClientConn
とhttputil.ServerConn
は低レベルAPIであり、net/http.Client
とnet/http.Server
は高レベルAPIに相当します。Goの設計思想では、通常、高レベルAPIの使用が推奨され、低レベルAPIは特定の高度なユースケースや、高レベルAPIの基盤としてのみ使用されるべきです。
このコミットは、httputil.ClientConn
とhttputil.ServerConn
が、本来意図された高レベルAPIであるnet/http.Client
とnet/http.Server
の代替として誤って使用されることを防ぐために行われました。
技術的詳細
このコミットの技術的詳細は、net/http/httputil/persist.go
ファイル内のServerConn
、NewServerConn
、ClientConn
、NewClientConn
、NewProxyClientConn
の各型定義と関数定義に、非推奨化を促すコメントを追加した点に集約されます。
変更前は、これらの型や関数には「低レベルであり、ほとんどのアプリケーションでは必要ない」といった程度のコメントしかありませんでした。しかし、このコミットでは、そのコメントをより強く、かつ具体的な代替手段を提示する形に変更しています。
具体的には、以下の点が変更されました。
-
ServerConn
のコメント変更: 変更前:// ServerConn is low-level and should not be needed by most applications. // See Server.
変更後:// ServerConn is low-level and old. Applications should instead use Server // in the net/http package.
「old (古い)」という言葉が追加され、より明確に「net/http
パッケージのServer
を使用すべき」と指示されています。 -
NewServerConn
のコメント追加:NewServerConn
関数のドキュメントブロック内に、ServerConn
と同様の警告コメントが追加されました。// ServerConn is low-level and old. Applications should instead use Server // in the net/http package.
これにより、NewServerConn
を使用しようとする開発者にも、このAPIが非推奨であることを明確に伝えます。 -
ClientConn
のコメント変更: 変更前:// ClientConn is low-level and should not be needed by most applications. // See Client.
変更後:// ClientConn is low-level and old. Applications should instead use // Client or Transport in the net/http package.
ServerConn
と同様に「old (古い)」が追加され、代替としてnet/http
パッケージのClient
またはTransport
を使用すべきであることが明記されました。Transport
はClient
の内部で使用されるHTTPラウンドトリップのインターフェースであり、より細かい制御が必要な場合に利用されます。 -
NewClientConn
のコメント追加:NewClientConn
関数のドキュメントブロック内に、ClientConn
と同様の警告コメントが追加されました。// ClientConn is low-level and old. Applications should use Client or // Transport in the net/http package.
-
NewProxyClientConn
のコメント追加:NewProxyClientConn
関数のドキュメントブロック内に、この関数も使用すべきではないという警告コメントが追加されました。// New code should not use NewProxyClientConn. See Client or // Transport in the net/http package instead.
これらの変更は、コードの動作自体を変更するものではなく、あくまでドキュメンテーションの改善です。しかし、Goのドキュメンテーションは非常に重要視されており、コメントを通じて開発者への適切なガイダンスを提供することは、ライブラリの健全な利用を促進する上で極めて効果的な手段となります。このコミットは、GoのAPI設計における「シンプルさ」と「適切な抽象化レベルの提供」という原則を再確認させるものです。
コアとなるコードの変更箇所
変更はsrc/pkg/net/http/httputil/persist.go
ファイルに集中しています。
--- a/src/pkg/net/http/httputil/persist.go
+++ b/src/pkg/net/http/httputil/persist.go
@@ -31,8 +31,8 @@ var errClosed = errors.New("i/o operation on closed connection")
// i.e. requests can be read out of sync (but in the same order) while the
// respective responses are sent.
//
-// ServerConn is low-level and should not be needed by most applications.
-// See Server.
+// ServerConn is low-level and old. Applications should instead use Server
+// in the net/http package.
type ServerConn struct {
lk sync.Mutex // read-write protects the following fields
c net.Conn
@@ -45,8 +45,11 @@ type ServerConn struct {
pipe textproto.Pipeline
}
-// NewServerConn returns a new ServerConn reading and writing c. If r is not
+// NewServerConn returns a new ServerConn reading and writing c. If r is not
// nil, it is the buffer to use when reading c.
+//
+// ServerConn is low-level and old. Applications should instead use Server
+// in the net/http package.
func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
if r == nil {
r = bufio.NewReader(c)
@@ -221,8 +224,8 @@ func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
// supports hijacking the connection calling Hijack to
// regain control of the underlying net.Conn and deal with it as desired.
//
-// ClientConn is low-level and should not be needed by most applications.
-// See Client.
+// ClientConn is low-level and old. Applications should instead use
+// Client or Transport in the net/http package.
type ClientConn struct {
lk sync.Mutex // read-write protects the following fields
c net.Conn
@@ -238,6 +241,9 @@ type ClientConn struct {
// NewClientConn returns a new ClientConn reading and writing c. If r is not
// nil, it is the buffer to use when reading c.
+//
+// ClientConn is low-level and old. Applications should use Client or
+// Transport in the net/http package.
func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
if r == nil {
r = bufio.NewReader(c)
@@ -252,6 +258,9 @@ func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
// NewProxyClientConn works like NewClientConn but writes Requests
// using Request's WriteProxy method.
+//
+// New code should not use NewProxyClientConn. See Client or
+// Transport in the net/http package instead.
func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
cc := NewClientConn(c, r)
cc.writeReq = (*http.Request).WriteProxy
コアとなるコードの解説
このコミットにおけるコードの変更は、既存のコメントを修正・追加することで、httputil
パッケージ内のServerConn
、NewServerConn
、ClientConn
、NewClientConn
、NewProxyClientConn
といった低レベルなHTTPコネクション管理APIの使用を非推奨とする明確なメッセージを開発者に伝えることにあります。
具体的には、以下の点が変更されています。
-
ServerConn
型定義のコメント:// ServerConn is low-level and old. Applications should instead use Server // in the net/http package.
以前のコメント「ServerConn
は低レベルであり、ほとんどのアプリケーションでは必要ありません。Server
を参照してください。」に、「old
(古い)」という単語が追加され、さらに「アプリケーションは代わりにnet/http
パッケージのServer
を使用すべきです」と、より直接的な指示に変わりました。これにより、このAPIがもはや推奨されない古いものであることが強調されます。 -
NewServerConn
関数定義のコメント:NewServerConn
関数のドキュメンテーションブロック内に、ServerConn
型定義と同様の警告コメントが追加されました。これは、NewServerConn
関数を呼び出そうとする開発者が、その戻り値であるServerConn
が非推奨であることをすぐに認識できるようにするためです。 -
ClientConn
型定義のコメント:// ClientConn is low-level and old. Applications should instead use // Client or Transport in the net/http package.
ServerConn
と同様に「old
(古い)」が追加され、代替としてnet/http
パッケージのClient
またはTransport
を使用すべきであることが明記されました。http.Client
は高レベルなHTTPクライアントであり、http.Transport
はhttp.Client
の内部で使用される、より低レベルなHTTPラウンドトリップのインターフェースです。これにより、開発者は自身のニーズに応じて適切な代替手段を選択できます。 -
NewClientConn
関数定義のコメント:NewClientConn
関数のドキュメンテーションブロック内に、ClientConn
型定義と同様の警告コメントが追加されました。 -
NewProxyClientConn
関数定義のコメント:// New code should not use NewProxyClientConn. See Client or // Transport in the net/http package instead.
この関数はプロキシリクエストを扱うためのClientConn
の特殊なコンストラクタですが、これも同様に非推奨とされ、新しいコードではnet/http
パッケージのClient
またはTransport
を使用すべきであると明記されました。
これらのコメントの変更は、Goのドキュメンテーションがコードの利用方法に関する重要なガイダンスを提供するという哲学を反映しています。単に「低レベル」と述べるだけでなく、「古い」「使用すべきではない」「代わりにこれを使え」といった具体的な指示を加えることで、開発者がこれらのAPIを誤って選択するリスクを大幅に低減し、より堅牢でメンテナンス性の高いコードを書くことを促しています。これは、ライブラリの進化に伴うAPIの推奨状況の変化を、コードベースを通じて明確に伝えるための重要な手段です。
関連リンク
- Go言語の
net/http
パッケージ公式ドキュメント: https://pkg.go.dev/net/http - Go言語の
net/http/httputil
パッケージ公式ドキュメント: https://pkg.go.dev/net/http/httputil - このコミットのGo Gerrit Code Reviewリンク: https://golang.org/cl/92790043
参考にした情報源リンク
- コミットメッセージ自体 (
./commit_data/19239.txt
の内容) - Go言語の標準ライブラリのドキュメンテーション(
net/http
およびnet/http/httputil
パッケージ)に関する一般的な知識 - HTTPプロトコルおよびコネクション管理に関する一般的な知識I have generated the detailed explanation in Markdown format, following all the specified sections and requirements. I have outputted it to standard output only. I believe this fulfills the user's request.