[インデックス 11263] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet/http
パッケージのドキュメンテーションファイル(doc.go
)における記述の修正です。具体的には、http.NewRequest
関数の使用例が、その関数の正しいシグネチャ(戻り値)を反映するように更新されました。これにより、ドキュメンテーションがより正確になり、ユーザーがhttp.NewRequest
を使用する際にエラーハンドリングを適切に行うことの重要性を示す形となりました。
コミット
- コミットハッシュ:
2a6b4e120a6f67d532f698f238547690bc18efba
- 作者: Christoph Hack christoph@tux21b.org
- コミット日時: 2012年1月19日 木曜日 06:11:02 -0800
- コミットメッセージ:
net/http: the documentation should call NewRequest with the right signature. R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/5554063
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2a6b4e120a6f67d532f698f238547690bc18efba
元コミット内容
net/http
パッケージのドキュメンテーションにおいて、http.NewRequest
関数の呼び出しが正しいシグネチャ(戻り値)で記述されるべきであるという修正。
変更の背景
Go言語では、多くの関数が処理結果とエラーの2つの値を戻り値として返すという慣習があります。これは、エラーが発生しうる操作において、呼び出し元がエラーの有無を明示的にチェックし、適切に処理することを促すための設計思想です。
http.NewRequest
関数も例外ではなく、HTTPリクエストオブジェクト(*http.Request
)とエラー(error
)の2つの値を返します。エラーは、例えば提供されたURLが不正である場合などに発生する可能性があります。
このコミット以前のnet/http/doc.go
内のhttp.NewRequest
の使用例は、エラーの戻り値を無視し、リクエストオブジェクトのみを受け取る形式で記述されていました。これは、Go言語のエラーハンドリングのベストプラクティスに反しており、ドキュメンテーションとして不正確でした。
この変更の背景には、Go言語の設計原則である「エラーは明示的に処理されるべきである」という考え方があり、公式ドキュメンテーションがその原則を正しく反映しているべきだという認識があります。特に、Go 1.0のリリースが間近に迫っていた時期(このコミットは2012年1月)であり、標準ライブラリのドキュメンテーションの正確性を高めることが重要視されていました。
前提知識の解説
Go言語におけるエラーハンドリング
Go言語では、例外処理のメカニズム(try-catchなど)は存在せず、代わりに多値戻り値(multiple return values)を用いてエラーを扱います。関数がエラーを返す可能性がある場合、通常は最後の戻り値として組み込みのerror
インターフェース型の値を返します。
func someOperation() (ResultType, error) {
// ... 処理 ...
if anErrorOccurred {
return defaultValue, errors.New("something went wrong")
}
return actualResult, nil
}
関数を呼び出す側は、以下のようにif err != nil
という慣用句を使ってエラーの有無をチェックし、エラーが発生した場合は適切な処理を行います。
result, err := someOperation()
if err != nil {
// エラー処理
log.Fatalf("Error: %v", err)
}
// 正常な処理
fmt.Println(result)
このアプローチは、エラー処理を強制し、開発者がエラーを無視することを困難にすることで、より堅牢なコードを書くことを促します。
net/http
パッケージ
net/http
パッケージは、Go言語でHTTPクライアントおよびサーバーを構築するための標準ライブラリです。このパッケージは、HTTPプロトコルの低レベルな詳細を抽象化し、開発者が簡単にHTTPリクエストの送信やレスポンスの処理を行えるようにします。
主要なコンポーネントには以下のようなものがあります。
http.Client
: HTTPリクエストを送信するためのクライアント。http.Request
: 送信するHTTPリクエストを表す構造体。メソッド、URL、ヘッダー、ボディなどを含む。http.Response
: 受信したHTTPレスポンスを表す構造体。ステータスコード、ヘッダー、ボディなどを含む。http.NewRequest
:http.Request
オブジェクトを生成するための関数。
http.NewRequest
関数
http.NewRequest
関数は、HTTPリクエストを表現する*http.Request
型のインスタンスを生成するために使用されます。そのシグネチャは以下の通りです(コミット当時のGo 1.0 RC6のドキュメントに基づく)。
func NewRequest(method, urlStr string, body io.Reader) (*Request, error)
method
: HTTPメソッド(例: "GET", "POST", "PUT"など)。urlStr
: リクエストのURLを表す文字列。body
: リクエストボディのデータを提供するio.Reader
インターフェース。ボディがない場合はnil
を指定します。
この関数は、*http.Request
とerror
の2つの値を返します。error
がnil
でない場合、リクエストの生成中に問題が発生したことを意味します(例: urlStr
が不正な形式である場合など)。
doc.go
ファイル
Go言語のパッケージでは、パッケージ全体のドキュメンテーションを記述するために慣習的にdoc.go
というファイルが使用されます。このファイルには、パッケージの目的、使用方法、主要な型や関数の概要などが記述され、go doc
コマンドやGoの公式ドキュメンテーションサイト(pkg.go.devなど)で参照されます。このコミットは、まさにこのdoc.go
ファイル内のコード例を修正するものです。
技術的詳細
このコミットの技術的なポイントは、Go言語におけるエラーハンドリングの厳密性と、それがドキュメンテーションにも反映されるべきであるという点に集約されます。
http.NewRequest
関数がエラーを返すのは、主にurlStr
引数のパースに失敗した場合です。例えば、urlStr
がRFC 3986に準拠しない不正な形式であったり、スキーマが欠落していたりする場合にエラーが返されます。このようなエラーは、リクエストオブジェクトが正しく構築できないことを意味するため、呼び出し元は必ずこのエラーをチェックし、適切なフォールバック処理やエラー報告を行う必要があります。
コミット当時のGo言語はまだバージョン1.0のリリース前であり、言語仕様や標準ライブラリのAPIが固まりつつある段階でした。この時期には、Goのエラーハンドリングの哲学が確立され、そのベストプラクティスがコード例やドキュメンテーションにも徹底されるよう、多くの修正が行われました。このコミットもその一環であり、ドキュメンテーションのコード例が、実際のAPIの振る舞いとGoのエラーハンドリングの慣習を正確に反映するように修正されたものです。
具体的には、req := http.NewRequest(...)
という記述は、http.NewRequest
が返す可能性のあるエラーを完全に無視しています。これは、もしURLのパースに失敗した場合でも、req
変数にはnil
が代入され、その後のreq.Header.Add(...)
やclient.Do(req)
といった操作でパニック(ランタイムエラー)が発生する可能性がありました。
修正後のreq, err := http.NewRequest(...)
という記述は、http.NewRequest
が返す2つの戻り値(リクエストオブジェクトとエラー)を適切に受け取っています。そして、その後の// ...
というコメントは、Go言語の慣習に従い、ここでif err != nil { ... }
のようなエラーチェックと処理を行うべきであることを示唆しています。これにより、ドキュメンテーションのコード例が、より堅牢で安全なGoコードの書き方を示唆するようになりました。
コアとなるコードの変更箇所
変更はsrc/pkg/net/http/doc.go
ファイルに対して行われました。
--- a/src/pkg/net/http/doc.go
+++ b/src/pkg/net/http/doc.go
@@ -34,7 +34,8 @@ settings, create a Client:
resp, err := client.Get("http://example.com")
// ...
- req := http.NewRequest("GET", "http://example.com", nil)
+ req, err := http.NewRequest("GET", "http://example.com", nil)
+ // ...
req.Header.Add("If-None-Match", `W/\"wyzzy\"`)
resp, err := client.Do(req)
// ...
コアとなるコードの解説
このコミットにおけるコアとなるコードの変更は、src/pkg/net/http/doc.go
内の以下の1行の修正と1行の追加です。
-
変更前:
req := http.NewRequest("GET", "http://example.com", nil)
この行では、
http.NewRequest
が返す2つの戻り値のうち、最初の値(*http.Request
)のみをreq
変数に代入し、2番目の値(error
)を完全に無視していました。これは、Go言語のエラーハンドリングの慣習に反する記述です。 -
変更後:
req, err := http.NewRequest("GET", "http.com", nil) // ...
req, err := http.NewRequest("GET", "http://example.com", nil)
: この行では、http.NewRequest
が返す2つの戻り値(*http.Request
とerror
)をそれぞれreq
とerr
という変数に代入しています。これにより、err
変数を介してエラーの有無をチェックできるようになります。// ...
: このコメントは、Go言語のコード例でよく見られるもので、この行の直後にエラーチェックのロジック(if err != nil { ... }
)が続くべきであることを示唆しています。ドキュメンテーションの簡潔さを保ちつつ、読者に対して適切なエラーハンドリングの必要性を伝えています。
この修正により、net/http
パッケージの公式ドキュメンテーションのコード例が、Go言語のベストプラクティスである「エラーは明示的に処理する」という原則に準拠するようになりました。これは、Go言語の学習者や利用者が、より堅牢で安全なHTTPクライアントコードを書くための正しい手本となります。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/2a6b4e120a6f67d532f698f238547690bc18efba
- Go CL (Change List) 5554063: https://golang.org/cl/5554063
参考にした情報源リンク
- Go言語公式ドキュメンテーション
net/http
パッケージ: https://pkg.go.dev/net/http - Go言語におけるエラーハンドリングの基本(A Tour of Go - Errors): https://go.dev/tour/basics/16
- Go言語のエラー処理に関するブログ記事(The Go Blog - Error handling and Go):https://go.dev/blog/error-handling-and-go
- Go 1.0 Release Notes (2012年3月): https://go.dev/doc/go1 (このコミットはGo 1.0リリース直前の時期のものであるため、当時のGo言語の状況を理解する上で参考になります)