[インデックス 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