[インデックス 14476] ファイルの概要
このコミットは、Go言語の net/http パッケージにおける Request 型の ParseForm メソッドと FormValue メソッドのドキュメントを明確化し、ParseForm の戻り値の型宣言における「スタッター(stutter)」を修正するものです。具体的には、ParseForm が r.Form を更新すること、およびPOST/PUTリクエストのボディパラメータがURLクエリ文字列の値よりも優先されることを明記し、FormValue のドキュメントに ParseForm の利用を促す記述を追加しています。
コミット
- コミットハッシュ:
62f54e129478f13954f92a13c4d012f23b05199f - 作者: Shenghou Ma minux.ma@gmail.com
- コミット日時: Mon Nov 26 20:03:24 2012 +0800
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/62f54e129478f13954f92a13c4d012f23b05199f
元コミット内容
net/http: clarify docs of ParseForm and mention ParseForm in docs for FormValue
while we're at it, also fix a return value stutter in ParseForm.
R=bradfitz
CC=golang-dev
https://golang.org/cl/6847074
変更の背景
このコミットの主な目的は、Go言語の標準ライブラリである net/http パッケージのドキュメントの明確性を向上させることです。特に、HTTPリクエストのフォームデータを解析する ParseForm メソッドと、その解析結果から特定の値を取得する FormValue メソッドに関する説明が不十分であったため、開発者がこれらのメソッドを正しく理解し、意図通りに使用できるようにするための改善が行われました。
具体的には、以下の点が背景にあります。
ParseFormの動作の不明瞭さ: 以前のドキュメントでは、ParseFormがRequestオブジェクトのFormフィールドを更新するという重要な副作用が明示されていませんでした。また、POST/PUTリクエストのボディパラメータがURLクエリパラメータよりも優先されるという挙動も明確ではありませんでした。これにより、開発者がフォームデータの取得順序や、ParseFormを呼び出すことによるRequestオブジェクトの状態変化を誤解する可能性がありました。FormValueと複数値の取得:FormValueは指定されたキーの最初の値のみを返します。しかし、HTMLフォームでは同じキーで複数の値を送信することが可能です(例: 複数のチェックボックス)。このような場合にすべての値を取得するためにはParseFormを呼び出した後にRequest.Formを直接参照する必要があるのですが、その点がFormValueのドキュメントから読み取れませんでした。- Go言語のコーディング規約への準拠: Go言語では、関数の戻り値の型が一つしかない場合、その型名を繰り返して書くことを「スタッター(stutter)」と呼び、避けるべき慣習とされています。
ParseFormメソッドのシグネチャがfunc (r *Request) ParseForm() (err error)となっていたため、これをfunc (r *Request) ParseForm() errorに修正することで、よりGoらしいコードスタイルに準拠させることが意図されました。これは機能的な変更ではなく、コードの可読性と慣習への適合性を高めるための改善です。
これらの改善により、net/http パッケージの使いやすさと堅牢性が向上し、開発者がより正確でバグの少ないWebアプリケーションを構築できるようになります。
前提知識の解説
このコミットを理解するためには、以下のGo言語およびHTTPプロトコルに関する基本的な知識が必要です。
-
Go言語の
net/httpパッケージ:- Go言語でWebサーバーやHTTPクライアントを構築するための標準ライブラリです。HTTPリクエストの処理、レスポンスの生成、ルーティングなど、Webアプリケーション開発に必要な機能を提供します。
http.Request構造体: HTTPリクエストを表す構造体です。クライアントからのリクエストに関するあらゆる情報(メソッド、URL、ヘッダー、ボディなど)を含みます。Request.Form:url.Values型のフィールドで、URLのクエリパラメータとPOST/PUTリクエストのボディパラメータ(フォームデータ)を結合したものを保持します。ParseFormまたはParseMultipartFormが呼び出された後にデータが格納されます。Request.PostForm:url.Values型のフィールドで、POSTまたはPUTリクエストのボディから解析されたフォームデータのみを保持します。url.Values:map[string][]stringのエイリアスで、キーと値のペア(キーに対して複数の値を持つことができる)を表現するために使用されます。HTTPのクエリパラメータやフォームデータを扱うのに適しています。
-
HTTPメソッド:
- GET: サーバーからリソースを取得するために使用されます。データはURLのクエリパラメータとして送信されます。
- POST: サーバーにデータを送信し、新しいリソースを作成するために使用されます。データはリクエストボディとして送信されます。
- PUT: サーバー上の既存のリソースを更新するために使用されます。データはリクエストボディとして送信されます。
-
URLクエリパラメータとリクエストボディ:
- URLクエリパラメータ: URLの
?の後に続くkey=value形式のデータです(例:http://example.com/search?q=golang&page=1)。主にGETリクエストで使用されます。 - リクエストボディ: HTTPリクエストの本体部分で、POSTやPUTリクエストで大量のデータを送信する際に使用されます。フォームデータ、JSON、XMLなど、様々な形式のデータを格納できます。
- URLクエリパラメータ: URLの
-
フォームデータの解析:
- Webアプリケーションでは、HTMLフォームから送信されたデータをサーバー側で解析する必要があります。Goの
net/httpパッケージは、この解析を自動的に行う機能を提供します。 Request.ParseForm(): URLのクエリパラメータと、POST/PUTリクエストのボディ(application/x-www-form-urlencodedまたはmultipart/form-data形式)を解析し、その結果をRequest.FormおよびRequest.PostFormに格納します。このメソッドは冪等(idempotent)であり、複数回呼び出しても同じ結果が得られます。Request.FormValue(key string):ParseFormまたはParseMultipartFormを必要に応じて自動的に呼び出し、指定されたキーのフォーム値を取得します。POST/PUTボディパラメータがURLクエリ文字列の値よりも優先されます。
- Webアプリケーションでは、HTMLフォームから送信されたデータをサーバー側で解析する必要があります。Goの
-
Go言語の「戻り値のスタッター(Return Value Stutter)」:
- Go言語の慣習として、関数の戻り値が一つしかない場合、その戻り値の型を括弧で囲んで明示的に名前付き戻り値として宣言する形式(例:
func foo() (result Type))は、型名が繰り返されるように見えるため「スタッター」と呼ばれ、避けるべきとされています。代わりに、func foo() Typeのように直接型を記述する形式が推奨されます。このコミットでは、ParseFormの戻り値の型が(err error)からerrorに変更され、この慣習に準拠しています。
- Go言語の慣習として、関数の戻り値が一つしかない場合、その戻り値の型を括弧で囲んで明示的に名前付き戻り値として宣言する形式(例:
技術的詳細
このコミットで行われた技術的な変更は、主に src/pkg/net/http/request.go ファイル内の ParseForm および FormValue メソッドのドキュメント文字列(コメント)の更新と、ParseForm メソッドのシグネチャの修正です。
-
ParseFormメソッドのドキュメントの明確化:- 変更前:
// ParseForm parses the raw query from the URL. // // For POST or PUT requests, it also parses the request body as a form. // POST and PUT body parameters take precedence over URL query string values. // If the request Body's size has not already been limited by MaxBytesReader, // the size is capped at 10MB. // // ParseMultipartForm calls ParseForm automatically. // It is idempotent. - 変更後:
// ParseForm parses the raw query from the URL and updates r.Form. // // For POST or PUT requests, it also parses the request body as a form and // put the results into both r.PostForm and r.Form. // POST and PUT body parameters take precedence over URL query string values // in r.Form. // If the request Body's size has not already been limited by MaxBytesReader, // the size is capped at 10MB. // // ParseMultipartForm calls ParseForm automatically. // It is idempotent. - 詳細:
- 最初の行に "
and updates r.Form" が追加され、ParseFormがRequestオブジェクトのFormフィールドを更新するという重要な副作用が明示されました。これは、開発者がParseFormを呼び出した後にr.Formを参照することで解析されたデータにアクセスできることを明確にします。 - POST/PUTリクエストに関する説明で、解析結果が "
both r.PostForm and r.Form" に格納されることが追記されました。これにより、PostFormがボディパラメータのみを、Formがクエリパラメータとボディパラメータを結合したものを保持するという違いがより明確になります。 - パラメータの優先順位に関する記述に "
in r.Form" が追加され、この優先順位がr.Formに反映されることが強調されました。
- 最初の行に "
- 変更前:
-
ParseFormメソッドのシグネチャの修正(戻り値のスタッターの修正):- 変更前:
func (r *Request) ParseForm() (err error) { - 変更後:
func (r *Request) ParseForm() error { var err error - 詳細:
- 戻り値の型宣言が
(err error)からerrorに変更されました。これは、Go言語のコーディング規約において、単一の戻り値を持つ関数で戻り値に名前を付ける(名前付き戻り値)ことで型名が繰り返される「スタッター」を避けるための修正です。機能的な変更はなく、コードのスタイルと可読性を向上させるためのものです。 - 名前付き戻り値
errが削除されたため、関数内でvar err errorと明示的にerr変数を宣言する行が追加されました。
- 戻り値の型宣言が
- 変更前:
-
FormValueメソッドのドキュメントの明確化:- 変更前:
// FormValue returns the first value for the named component of the query. // POST and PUT body parameters take precedence over URL query string values. // FormValue calls ParseMultipartForm and ParseForm if necessary. - 変更後:
// FormValue returns the first value for the named component of the query. // POST and PUT body parameters take precedence over URL query string values. // FormValue calls ParseMultipartForm and ParseForm if necessary. // To access multiple values of the same key use ParseForm. - 詳細:
- 最後の行に "
To access multiple values of the same key use ParseForm." が追加されました。これは、FormValueが単一の値しか返さないため、同じキーを持つ複数の値(例: 複数のチェックボックス)を取得したい場合には、ParseFormを呼び出した後にRequest.Formを直接参照する必要があることを開発者に明確に伝えるための重要な情報です。
- 最後の行に "
- 変更前:
これらの変更は、Goの net/http パッケージのドキュメントの精度と完全性を高め、開発者がWebアプリケーションでフォームデータを扱う際の混乱を減らすことを目的としています。
コアとなるコードの変更箇所
--- a/src/pkg/net/http/request.go
+++ b/src/pkg/net/http/request.go
@@ -643,16 +643,20 @@ func parsePostForm(r *Request) (vs url.Values, err error) {
return
}
-// ParseForm parses the raw query from the URL.
+// ParseForm parses the raw query from the URL and updates r.Form.
+//
+// For POST or PUT requests, it also parses the request body as a form and
+// put the results into both r.PostForm and r.Form.
+// POST and PUT body parameters take precedence over URL query string values
+// in r.Form.
//
-// For POST or PUT requests, it also parses the request body as a form.
-// POST and PUT body parameters take precedence over URL query string values.
// If the request Body's size has not already been limited by MaxBytesReader,
// the size is capped at 10MB.
//
// ParseMultipartForm calls ParseForm automatically.
// It is idempotent.
-func (r *Request) ParseForm() (err error) {
+func (r *Request) ParseForm() error {
+\tvar err error
\tif r.PostForm == nil {\
\t\tif r.Method == \"POST\" || r.Method == \"PUT\" {\
\t\t\tr.PostForm, err = parsePostForm(r)\
@@ -728,6 +732,7 @@ func (r *Request) ParseMultipartForm(maxMemory int64) error {
// FormValue returns the first value for the named component of the query.\
// POST and PUT body parameters take precedence over URL query string values.\
// FormValue calls ParseMultipartForm and ParseForm if necessary.\
+// To access multiple values of the same key use ParseForm.\
func (r *Request) FormValue(key string) string {\
\tif r.Form == nil {\
\t\tr.ParseMultipartForm(defaultMaxMemory)\
コアとなるコードの解説
上記のdiffは、src/pkg/net/http/request.go ファイルにおける以下の3つの主要な変更を示しています。
-
ParseFormメソッドのドキュメントコメントの変更:- // ParseForm parses the raw query from the URL.- 元のドキュメントの最初の行です。
+ // ParseForm parses the raw query from the URL and updates r.Form.ParseFormがRequestオブジェクトのFormフィールドを更新するという重要な情報を追加しました。これにより、開発者はこのメソッドが単に解析するだけでなく、リクエストオブジェクトの状態を変更することを明確に理解できます。
- // For POST or PUT requests, it also parses the request body as a form.- 元のドキュメントのPOST/PUTリクエストに関する説明です。
+ // For POST or PUT requests, it also parses the request body as a form and+ // put the results into both r.PostForm and r.Form.- POST/PUTリクエストのボディが解析された結果が、
r.PostFormとr.Formの両方に格納されることを明示しました。これは、r.PostFormがボディデータのみを、r.FormがURLクエリとボディデータを結合したものを保持するというRequest構造体の設計をより正確に反映しています。
- POST/PUTリクエストのボディが解析された結果が、
- // POST and PUT body parameters take precedence over URL query string values.- 元のドキュメントの優先順位に関する説明です。
+ // POST and PUT body parameters take precedence over URL query string values+ // in r.Form.- POST/PUTボディパラメータがURLクエリ文字列の値よりも優先されるというルールが、具体的に
r.Formに適用されることを明確にしました。
- POST/PUTボディパラメータがURLクエリ文字列の値よりも優先されるというルールが、具体的に
-
ParseFormメソッドのシグネチャの変更(戻り値のスタッターの修正):- func (r *Request) ParseForm() (err error) {- 元の
ParseFormメソッドのシグネチャです。err errorという名前付き戻り値が使用されています。
- 元の
+ func (r *Request) ParseForm() error {- 戻り値の型宣言から
errという名前が削除され、単にerrorとなりました。これはGo言語のコーディング規約で推奨されるスタイルであり、単一の戻り値を持つ関数で戻り値に名前を付けることによる「スタッター」を避けるための修正です。
- 戻り値の型宣言から
+ \tvar err error- 名前付き戻り値が削除されたため、関数内で
err変数を使用する前に明示的にvar err errorと宣言する必要が生じました。これは機能的な変更ではなく、シグネチャの変更に伴うコードの調整です。
- 名前付き戻り値が削除されたため、関数内で
-
FormValueメソッドのドキュメントコメントの変更:+ // To access multiple values of the same key use ParseForm.FormValueが単一の値しか返さないため、同じキーを持つ複数の値を取得したい場合にはParseFormを呼び出した後にRequest.Formを直接参照する必要があることを開発者に促す新しい行が追加されました。これは、FormValueの限界と、より高度なフォームデータ処理のための適切なアプローチを明確にするものです。
これらの変更は、Goの net/http パッケージのドキュメントの正確性、完全性、およびGoのコーディング慣習への準拠を向上させることを目的としています。
関連リンク
- Go CL (Change List) 6847074: https://golang.org/cl/6847074
参考にした情報源リンク
- (この解説は提供されたコミット情報とGo言語の一般的な知識に基づいており、追加のWeb検索は行っていません。)
- Go言語の
net/httpパッケージのドキュメント: https://pkg.go.dev/net/http - Go言語のEffective Go (特に「Return values」セクション): https://go.dev/doc/effective_go#return_values
- Go言語の
url.Valuesドキュメント: https://pkg.go.dev/net/url#Values