Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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パッケージに含まれるClientConnServerConnという低レベルなHTTPコネクション管理APIが、Go 1のリリース時に意図せず含まれてしまい、その後もメンテナンスされずに放置されていたという問題があります。

コミットメッセージによると、Gopherconで一人の開発者がhttputil.ClientConnを使用している問題のデバッグを手伝った際に、コミッターであるBrad Fitzpatrick氏がこれらのAPIがGo 1に存在することに驚愕したと述べています。これらのAPIは、net/httpパッケージのより高レベルなClientServer型とは異なり、Goの標準HTTPスタックでは内部的に使用されておらず、4年以上も手つかずのままでした。

このような状況は、開発者が意図しない低レベルAPIを使用してしまい、予期せぬ問題や将来的な互換性の問題に直面するリスクをはらんでいました。そのため、これらのAPIの使用を積極的に discourage (推奨しない) し、より適切でメンテナンスされたnet/httpパッケージのAPIへの移行を促す必要がありました。このコミットは、その目的のためにドキュメントに警告を追加することで、開発者への明確なガイダンスを提供することを意図しています。

前提知識の解説

このコミットを理解するためには、Go言語のnet/httpパッケージと、net/http/httputilパッケージの役割、そしてHTTPプロトコルにおけるコネクション管理の基本的な概念を理解しておく必要があります。

  1. net/httpパッケージ: Go言語の標準ライブラリで、HTTPクライアントとサーバーの実装を提供します。

    • http.Server: HTTPリクエストを処理するためのサーバー機能を提供します。通常、http.ListenAndServe関数を通じて利用され、リクエストのルーティング、ハンドリング、レスポンスの送信など、高レベルなサーバー機能を提供します。
    • http.Client: HTTPリクエストを送信するためのクライアント機能を提供します。http.Gethttp.Postなどの便利な関数を通じて利用され、コネクションの再利用、リダイレクトの処理、タイムアウト設定など、高レベルなクライアント機能を提供します。
    • コネクション管理: http.Clienthttp.Serverは、内部的にHTTP/1.1の永続的コネクション(Keep-Alive)やコネクションプーリングなどを自動的に処理し、効率的な通信を実現します。開発者は通常、これらの低レベルなコネクション管理の詳細を意識する必要はありません。
  2. net/http/httputilパッケージ: net/httpパッケージを補完するユーティリティ機能を提供します。これには、リバースプロキシ、ダンプ機能、そして本コミットの対象であるClientConnServerConnのような低レベルなコネクション管理プリミティブが含まれていました。

    • httputil.ClientConn: HTTPクライアント側で、単一のTCPコネクション上でHTTPリクエストとレスポンスを低レベルでやり取りするための構造体です。これは、net.Connをラップし、リクエストの書き込みとレスポンスの読み込みを直接制御することを目的としていました。
    • httputil.ServerConn: HTTPサーバー側で、単一のTCPコネクション上でHTTPリクエストとレスポンスを低レベルでやり取りするための構造体です。こちらもnet.Connをラップし、リクエストの読み込みとレスポンスの書き込みを直接制御することを目的としていました。
  3. 低レベルAPIと高レベルAPI: ソフトウェア開発において、APIは通常、低レベルなものと高レベルなものに分類されます。

    • 低レベルAPI: ハードウェアやOSの機能に直接アクセスするなど、より細かい制御を可能にするが、使用が複雑で、誤用すると問題を引き起こしやすい傾向があります。
    • 高レベルAPI: 低レベルAPIの上に構築され、より抽象化された機能を提供します。使用が簡単で、一般的なユースケースに適していますが、細かい制御は制限される場合があります。 httputil.ClientConnhttputil.ServerConnは低レベルAPIであり、net/http.Clientnet/http.Serverは高レベルAPIに相当します。Goの設計思想では、通常、高レベルAPIの使用が推奨され、低レベルAPIは特定の高度なユースケースや、高レベルAPIの基盤としてのみ使用されるべきです。

このコミットは、httputil.ClientConnhttputil.ServerConnが、本来意図された高レベルAPIであるnet/http.Clientnet/http.Serverの代替として誤って使用されることを防ぐために行われました。

技術的詳細

このコミットの技術的詳細は、net/http/httputil/persist.goファイル内のServerConnNewServerConnClientConnNewClientConnNewProxyClientConnの各型定義と関数定義に、非推奨化を促すコメントを追加した点に集約されます。

変更前は、これらの型や関数には「低レベルであり、ほとんどのアプリケーションでは必要ない」といった程度のコメントしかありませんでした。しかし、このコミットでは、そのコメントをより強く、かつ具体的な代替手段を提示する形に変更しています。

具体的には、以下の点が変更されました。

  1. 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を使用すべき」と指示されています。

  2. NewServerConnのコメント追加: NewServerConn関数のドキュメントブロック内に、ServerConnと同様の警告コメントが追加されました。 // ServerConn is low-level and old. Applications should instead use Server // in the net/http package. これにより、NewServerConnを使用しようとする開発者にも、このAPIが非推奨であることを明確に伝えます。

  3. 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を使用すべきであることが明記されました。TransportClientの内部で使用されるHTTPラウンドトリップのインターフェースであり、より細かい制御が必要な場合に利用されます。

  4. NewClientConnのコメント追加: NewClientConn関数のドキュメントブロック内に、ClientConnと同様の警告コメントが追加されました。 // ClientConn is low-level and old. Applications should use Client or // Transport in the net/http package.

  5. 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パッケージ内のServerConnNewServerConnClientConnNewClientConnNewProxyClientConnといった低レベルなHTTPコネクション管理APIの使用を非推奨とする明確なメッセージを開発者に伝えることにあります。

具体的には、以下の点が変更されています。

  1. ServerConn型定義のコメント: // ServerConn is low-level and old. Applications should instead use Server // in the net/http package. 以前のコメント「ServerConnは低レベルであり、ほとんどのアプリケーションでは必要ありません。Serverを参照してください。」に、「old(古い)」という単語が追加され、さらに「アプリケーションは代わりにnet/httpパッケージのServerを使用すべきです」と、より直接的な指示に変わりました。これにより、このAPIがもはや推奨されない古いものであることが強調されます。

  2. NewServerConn関数定義のコメント: NewServerConn関数のドキュメンテーションブロック内に、ServerConn型定義と同様の警告コメントが追加されました。これは、NewServerConn関数を呼び出そうとする開発者が、その戻り値であるServerConnが非推奨であることをすぐに認識できるようにするためです。

  3. 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.Transporthttp.Clientの内部で使用される、より低レベルなHTTPラウンドトリップのインターフェースです。これにより、開発者は自身のニーズに応じて適切な代替手段を選択できます。

  4. NewClientConn関数定義のコメント: NewClientConn関数のドキュメンテーションブロック内に、ClientConn型定義と同様の警告コメントが追加されました。

  5. 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の推奨状況の変化を、コードベースを通じて明確に伝えるための重要な手段です。

関連リンク

参考にした情報源リンク

  • コミットメッセージ自体 (./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.