[インデックス 11961] ファイルの概要
このコミットは、Go言語の標準ライブラリである net/url
パッケージにおいて、ParseWithReference
関数を ParseWithFragment
に名称変更するものです。この変更は、関数の目的をより正確に反映させ、URLのフラグメント(#
以降の部分)の解析に特化していることを明確にするために行われました。また、この名称変更に伴い、既存のコードベースを自動的に更新するための go fix
ツール用の新しいルールが追加されています。
コミット
- コミットハッシュ:
8342793e7bc9ea38629893763eeef9a3f4fdc836
- Author: David Symonds dsymonds@golang.org
- Date: Thu Feb 16 15:56:03 2012 +1100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8342793e7bc9ea386629893763eeef9a3f4fdc836
元コミット内容
net/url: Rename ParseWithReference to ParseWithFragment.
Updates #2946.
R=golang-dev, r, r
CC=golang-dev
https://golang.org/cl/5671061
変更の背景
この変更の主な背景は、net/url
パッケージ内の ParseWithReference
関数の命名がその実際の機能と一致していなかった点にあります。URLの「参照(Reference)」という用語は、URIの一般的な概念においてより広範な意味を持つため、特定のURLの「フラグメント(Fragment)」部分(URLの #
以降の部分)を解析する機能を持つこの関数には誤解を招く可能性がありました。
Go言語のIssue #2946(net/url
: API)では、net/url
パッケージのAPIに関する議論が行われており、その中でこの命名の曖昧さが指摘されました。開発チームは、関数の名前を ParseWithFragment
に変更することで、その役割をより明確にし、将来的な混乱を避けることを決定しました。これにより、コードの可読性と保守性が向上し、開発者が関数の意図をより正確に理解できるようになります。
また、このようなAPIの変更は、既存のGoプログラムに影響を与える可能性があります。Go言語では、後方互換性を維持しつつ、必要に応じてAPIの改善を行うために go fix
ツールが提供されています。このコミットでは、ParseWithReference
から ParseWithFragment
への名称変更を自動的に処理するための go fix
ルールも同時に導入されており、既存のコードベースの移行を容易にしています。
前提知識の解説
net/url
パッケージ
net/url
パッケージは、Go言語の標準ライブラリの一部であり、URL(Uniform Resource Locator)の解析、生成、および操作のための機能を提供します。このパッケージは、ウェブアプリケーションやネットワークプログラミングにおいて、URLを安全かつ効率的に扱うために不可欠です。
主な機能には以下のようなものがあります。
- URLの解析: 文字列形式のURLを構造化された
url.URL
型のオブジェクトに解析し、スキーム、ホスト、パス、クエリ、フラグメントなどの各コンポーネントにアクセスできるようにします。 - URLの構築: 各コンポーネントからURL文字列を構築します。
- クエリパラメータの操作: URLのクエリパラメータを簡単に操作するための機能を提供します。
- エスケープ/アンエスケープ: URLエンコーディングとデコーディングを処理します。
URLのフラグメント(Fragment)
URLのフラグメントは、URLの末尾に #
(ハッシュ記号)に続いて記述される部分です。例えば、http://example.com/path/to/page.html#section1
というURLでは、section1
がフラグメントです。
フラグメントは、通常、ウェブページ内の特定の部分(アンカー)を指し示すために使用されます。ブラウザは、フラグメントに基づいてページ内の指定された位置までスクロールしますが、フラグメントの情報は通常、HTTPリクエストとしてサーバーに送信されません。これは、フラグメントがクライアントサイドでのみ意味を持つ情報であるためです。
go fix
ツール
go fix
は、Go言語のコマンドラインツールの一つで、Goのバージョンアップに伴うAPIの変更や非推奨になった機能の使用箇所を、自動的に新しいAPIや推奨される書き方に修正するために使用されます。これにより、Go言語の進化に合わせて既存のコードベースを容易に更新できるようになります。
go fix
は、Goのソースコードを解析し、特定のパターンに一致するコードを見つけると、それを定義された新しいパターンに置き換えます。このツールは、Go言語のバージョンアップ時に開発者の移行コストを大幅に削減するのに役立ちます。
このコミットでは、ParseWithReference
から ParseWithFragment
への名称変更を自動化するために、go fix
の新しいルールが追加されました。これにより、開発者は手動で全ての呼び出し箇所を修正する必要がなくなり、よりスムーズな移行が可能になります。
技術的詳細
このコミットの技術的詳細は、主に以下の3つの側面に焦点を当てています。
-
net/url
パッケージ内の関数名称変更:src/pkg/net/url/url.go
ファイルにおいて、ParseWithReference
関数がParseWithFragment
に名称変更されました。- 関数のシグネチャも
func ParseWithReference(rawurlref string) (url *URL, err error)
からfunc ParseWithFragment(rawurl string) (url *URL, err error)
に変更されています。引数名もrawurlref
からrawurl
に変更され、より簡潔になりました。 - 関数内部のロジックも、引数名の変更に合わせて
rawurlref
がrawurl
に、split
関数の戻り値の変数名がrawurl, frag
からu, frag
に変更されています。これにより、コードの意図がより明確になります。 - エラーメッセージ内の引数も
rawurlref
からrawurl
に変更され、一貫性が保たれています。
-
テストコードの更新:
src/pkg/net/url/url_test.go
ファイルにおいて、ParseWithReference
を呼び出していたテスト関数やテストケースが、新しいParseWithFragment
を呼び出すように更新されました。- 具体的には、
TestParseWithReference
関数がTestParseWithFragment
に、DoTest
およびDoTestString
の呼び出しにおける関数名引数もParseWithReference
からParseWithFragment
に変更されています。 resolveReferenceTests
およびTestResolveReferenceOpaque
内のmustParse
ヘルパー関数も、ParseWithReference
の代わりにParseWithFragment
を使用するように更新されています。これにより、変更されたAPIに対するテストカバレッジが維持されます。
-
go fix
ツールのための新しいルールの追加:src/cmd/fix/url2.go
およびsrc/cmd/fix/url2_test.go
という新しいファイルが追加されました。これらは、go fix
ツールがParseWithReference
の呼び出しをParseWithFragment
に自動的に修正するためのルールを定義しています。url2.go
では、fix
構造体としてurl2Fix
が定義され、url2
関数が実際の修正ロジックを実装しています。このurl2
関数は、net/url
パッケージをインポートしているファイルに対して、url.ParseWithReference
の呼び出しをurl.ParseWithFragment
に置き換える処理を行います。go/ast
パッケージを使用してAST(抽象構文木)を走査し、ast.SelectorExpr
(セレクタ式、例:url.ParseWithReference
)を特定して名前を書き換えます。url2_test.go
では、url2.go
で定義されたgo fix
ルールのテストケースが記述されています。これにより、go fix
ツールが正しく機能することを確認できます。テストケースは、ParseWithReference
を含む入力コードが、ParseWithFragment
に修正された出力コードになることを検証します。
これらの変更は、APIの明確化、既存コードの自動移行支援、およびテストカバレッジの維持という点で、Go言語の設計思想と開発プロセスにおけるベストプラクティスを反映しています。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。
doc/go1.html
doc/go1.tmpl
src/cmd/fix/url2.go
(新規追加)src/cmd/fix/url2_test.go
(新規追加)src/pkg/net/url/url.go
src/pkg/net/url/url_test.go
特に重要な変更は src/pkg/net/url/url.go
と src/cmd/fix/url2.go
にあります。
src/pkg/net/url/url.go
--- a/src/pkg/net/url/url.go
+++ b/src/pkg/net/url/url.go
@@ -415,18 +415,18 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
return
}
-// ParseWithReference is like Parse but allows a trailing #fragment.
-func ParseWithReference(rawurlref string) (url *URL, err error) {
+// ParseWithFragment is like Parse but allows a trailing #fragment.
+func ParseWithFragment(rawurl string) (url *URL, err error) {
// Cut off #frag
-\trawurl, frag := split(rawurlref, '#', true)\
-\tif url, err = Parse(rawurl); err != nil {\
+\tu, frag := split(rawurl, '#', true)\
+\tif url, err = Parse(u); err != nil {\
\t\treturn nil, err
\t}\
\tif frag == "" {\
\t\treturn url, nil
\t}\
\tif url.Fragment, err = unescape(frag, encodeFragment); err != nil {\
-\t\treturn nil, &Error{\"parse\", rawurlref, err}\
+\t\treturn nil, &Error{\"parse\", rawurl, err}\
\t}\
\treturn url, nil
}
src/cmd/fix/url2.go
(新規追加)
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "go/ast"
func init() {
register(url2Fix)
}
var url2Fix = fix{
"url2",
"2012-02-16",
url2,
`Rename some functions in net/url.
http://codereview.appspot.com/5671061
`,
}
func url2(f *ast.File) bool {
if !imports(f, "net/url") {
return false
}
fixed := false
walk(f, func(n interface{}) {
// Rename functions and methods.
sel, ok := n.(*ast.SelectorExpr)
if !ok {
return
}
if !isTopName(sel.X, "url") {
return
}
if sel.Sel.Name == "ParseWithReference" {
sel.Sel.Name = "ParseWithFragment"
fixed = true
}
})
return fixed
}
コアとなるコードの解説
src/pkg/net/url/url.go
の変更
このファイルでは、ParseWithReference
関数が ParseWithFragment
に名称変更され、そのシグネチャと内部の実装が更新されています。
- 関数名の変更:
ParseWithReference
からParseWithFragment
への変更は、この関数がURLのフラグメント部分(#
以降)の解析に特化していることを明確にします。 - 引数名の変更:
rawurlref
からrawurl
への変更は、引数が生のURL文字列全体であることをより簡潔に示します。 - 内部ロジックの調整:
split
関数の戻り値の変数名がrawurl, frag
からu, frag
に変更されています。これは、rawurl
という変数名が関数の引数として既に存在するため、シャドーイングを避けるための良いプラクティスです。Parse(rawurl)
の代わりにParse(u)
を呼び出すことで、引数として渡された元のrawurl
ではなく、フラグメント部分を切り離した後のURL文字列がParse
関数に渡されることを保証します。 - エラーメッセージの更新: エラー発生時に返される
Error
構造体のrawurlref
フィールドがrawurl
に変更され、一貫性が保たれています。
これらの変更は、関数の意図を明確にし、コードの可読性と保守性を向上させることを目的としています。
src/cmd/fix/url2.go
の新規追加
このファイルは、go fix
ツールが ParseWithReference
の呼び出しを自動的に ParseWithFragment
に修正するためのロジックを定義しています。
init()
関数:register(url2Fix)
を呼び出すことで、この修正ルールをgo fix
ツールに登録します。url2Fix
変数:fix
構造体として定義され、この修正ルールの名前("url2"
)、適用日("2012-02-16"
)、実際の修正ロジックを実装する関数(url2
)、および説明を提供します。url2(f *ast.File) bool
関数:imports(f, "net/url")
で、現在のファイルがnet/url
パッケージをインポートしているかどうかを確認します。インポートしていない場合は、修正の必要がないためfalse
を返します。walk(f, func(n interface{}) { ... })
を使用して、ファイルのAST(抽象構文木)を走査します。ASTは、Goのソースコードを構造化されたツリー形式で表現したものです。- 走査中に、各ノードが
*ast.SelectorExpr
(セレクタ式、例:url.ParseWithReference
)であるかどうかを確認します。 isTopName(sel.X, "url")
で、セレクタ式の左側(sel.X
)がurl
という名前(つまり、url.ParseWithReference
のurl
部分)であるかどうかを確認します。sel.Sel.Name == "ParseWithReference"
で、セレクタ式の右側(sel.Sel.Name
)がParseWithReference
であるかどうかを確認します。- これらの条件がすべて満たされた場合、
sel.Sel.Name = "ParseWithFragment"
を実行して、関数名をParseWithFragment
に書き換えます。 fixed = true
を設定し、ファイルが修正されたことを示します。- 最終的に
fixed
の値を返すことで、go fix
ツールにファイルが変更されたかどうかを通知します。
この go fix
ルールにより、開発者は手動でコードを修正する手間を省き、Go言語のAPI変更に迅速に対応できるようになります。
関連リンク
- Go CL (Code Review) リンク: https://golang.org/cl/5671061
- GitHub コミットページ: https://github.com/golang/go/commit/8342793e7bc9ea38629893763eeef9a3f4fdc836
参考にした情報源リンク
- Go issue 2946:
net/url
: API (GitHub): https://github.com/golang/go/issues/2946 - Go
net/url
package documentation: https://pkg.go.dev/net/url - Go by Example: URL Parsing: https://gobyexample.com/url-parsing
- Go
go fix
command documentation: https://pkg.go.dev/cmd/go#hdr-Fix_packages