[インデックス 11754] ファイルの概要
このコミットは、Go言語の標準ライブラリであるregexp
パッケージ内のFindStringIndex
およびFindReaderIndex
関数の戻り値に、名前付き戻り値パラメータloc
を追加する変更です。これにより、これらの関数のドキュメントとの整合性が向上し、コードの可読性がわずかに向上します。
コミット
commit 9cd4a0467ae2494b0734693b90d47c604610a9ac
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Fri Feb 10 10:22:01 2012 +1100
regexp: name result parameters referenced from docs
Fixes #2953
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5653051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9cd4a0467ae2494b0734693b90d47c604610a9ac
元コミット内容
regexp: name result parameters referenced from docs
Fixes #2953
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5653051
変更の背景
この変更は、Go言語のIssue #2953「regexp: document FindStringIndex's return value as loc
」に対応するものです。このIssueでは、regexp
パッケージのFindStringIndex
関数のドキュメントが、戻り値の[]int
スライスをloc
という名前で参照しているにもかかわらず、実際の関数シグネチャでは名前付き戻り値パラメータが使用されていない点が指摘されていました。
ドキュメントとコードの間のこの不一致は、開発者がドキュメントを読んだ際に、戻り値が具体的に何を意味するのか、あるいはどのように参照されるべきかについて混乱を招く可能性がありました。特に、loc[0]
とloc[1]
がそれぞれマッチの開始と終了インデックスを示すという説明があるため、loc
という名前がコード上でも明示されている方が、ドキュメントの意図がより明確に伝わります。
このコミットは、このドキュメントとコードの間の整合性の問題を解決し、コードの可読性とドキュメントの正確性を向上させることを目的としています。
前提知識の解説
Go言語のregexp
パッケージ
Go言語のregexp
パッケージは、正規表現を扱うための標準ライブラリです。Perl、Python、その他の言語で一般的に使用される正規表現の構文とセマンティクスをサポートしています。このパッケージは、文字列内でのパターンマッチング、部分文字列の検索、置換などの機能を提供します。
Regexp
型: コンパイルされた正規表現を表す型です。FindStringIndex(s string) []int
: 指定された文字列s
内で正規表現に最初にマッチする部分の開始インデックスと終了インデックスを[]int
スライスとして返します。マッチが見つからない場合はnil
を返します。戻り値の[]int
スライスは、[開始インデックス, 終了インデックス]
の形式です。FindReaderIndex(r io.RuneReader) []int
:io.RuneReader
から読み取ったテキスト内で正規表現に最初にマッチする部分の開始インデックスと終了インデックスを[]int
スライスとして返します。マッチが見つからない場合はnil
を返します。
Go言語の名前付き戻り値パラメータ
Go言語では、関数の戻り値に名前を付けることができます。これを「名前付き戻り値パラメータ (Named Return Parameters)」と呼びます。
通常の戻り値の宣言:
func add(a, b int) int {
return a + b
}
名前付き戻り値パラメータの宣言:
func add(a, b int) (sum int) {
sum = a + b
return // sum が自動的に返される
}
名前付き戻り値パラメータを使用する利点は以下の通りです。
- 可読性の向上: 戻り値が何を意味するのかが明確になります。特に複数の戻り値がある場合に有効です。
- ドキュメントとの整合性: ドキュメントで特定の名前で参照されている戻り値を、コード上でもその名前で明示できます。
defer
との連携:defer
文内で名前付き戻り値パラメータを変更することで、関数の終了直前に戻り値を操作できます。- ゼロ値の初期化: 名前付き戻り値パラメータは、関数が開始される際にその型のゼロ値で自動的に初期化されます。
このコミットでは、FindStringIndex
とFindReaderIndex
の戻り値がドキュメントでloc
として参照されているため、コード上でもloc
という名前を明示することで、ドキュメントとの整合性を高めています。
技術的詳細
このコミットの技術的な変更は非常にシンプルですが、Go言語の設計思想とドキュメンテーションの重要性を示しています。
変更の核心は、regexp
パッケージ内の2つの関数、FindStringIndex
とFindReaderIndex
の関数シグネチャに名前付き戻り値パラメータloc
を追加することです。
変更前:
func (re *Regexp) FindStringIndex(s string) []int {
// ...
return nil
}
func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
// ...
return nil
}
変更後:
func (re *Regexp) FindStringIndex(s string) (loc []int) {
// ...
return nil // または return loc
}
func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
// ...
return nil // または return loc
}
この変更により、関数内部でloc
という変数が自動的に宣言され、[]int
型のゼロ値(nil
スライス)で初期化されます。関数本体のロジックは、以前と同様にre.doExecute
の結果をa
に代入し、そのa
を返しています。Go言語では、名前付き戻り値パラメータが宣言されている場合、return
ステートメントで明示的に値を指定しない場合(裸のreturn
)、名前付き戻り値パラメータの現在の値が返されます。しかし、このケースではa
を直接返しているため、loc = a; return
と書くのと同じ効果になります。
重要なのは、この変更が関数の外部からの呼び出し方や動作に影響を与えないことです。呼び出し元は引き続き[]int
スライスを受け取ります。しかし、ドキュメントでloc
という名前で説明されている戻り値が、コード上でもその名前で明示されることで、ドキュメントとコードの間のギャップが埋まり、開発者がドキュメントを読んだ際の理解が深まります。
これは、Go言語の「自己文書化コード」の原則を強化する小さな一歩とも言えます。コード自体がその意図をより明確に伝えることで、外部ドキュメントへの依存を減らし、メンテナンス性を向上させます。
コアとなるコードの変更箇所
変更はsrc/pkg/regexp/regexp.go
ファイルにあります。
--- a/src/pkg/regexp/regexp.go
+++ b/src/pkg/regexp/regexp.go
@@ -676,7 +676,7 @@ func (re *Regexp) FindString(s string) string {
// location of the leftmost match in s of the regular expression. The match
// itself is at s[loc[0]:loc[1]].
// A return value of nil indicates no match.
-func (re *Regexp) FindStringIndex(s string) []int {
+func (re *Regexp) FindStringIndex(s string) (loc []int) {
a := re.doExecute(nil, nil, s, 0, 2)
if a == nil {
return nil
@@ -688,7 +688,7 @@ func (re *Regexp) FindStringIndex(s string) []int {
// location of the leftmost match of the regular expression in text read from
// the RuneReader. The match itself is at s[loc[0]:loc[1]]. A return
// value of nil indicates no match.
-func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
+func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
a := re.doExecute(r, nil, "", 0, 2)
if a == nil {
return nil
コアとなるコードの解説
上記のdiffを見ると、以下の2つの関数のシグネチャが変更されていることがわかります。
-
func (re *Regexp) FindStringIndex(s string) []int
- 変更前は、戻り値の型
[]int
のみが指定されていました。 - 変更後は、
func (re *Regexp) FindStringIndex(s string) (loc []int)
となり、戻り値の[]int
スライスにloc
という名前が付けられました。
- 変更前は、戻り値の型
-
func (re *Regexp) FindReaderIndex(r io.RuneReader) []int
- 変更前は、戻り値の型
[]int
のみが指定されていました。 - 変更後は、
func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int)
となり、戻り値の[]int
スライスにloc
という名前が付けられました。
- 変更前は、戻り値の型
関数本体のロジック(re.doExecute
の呼び出しやnil
チェック、a
の返却)には一切変更がありません。これは、名前付き戻り値パラメータが導入されても、関数内部でその名前の変数を明示的に使用する必要はなく、最終的にreturn
ステートメントで返される値がその名前付きパラメータに割り当てられるためです。この場合、a
がloc
に割り当てられて返されます。
この変更は、コードの機能的な動作には影響を与えず、主にドキュメントとの整合性とコードの自己文書化能力を向上させるためのものです。ドキュメントで「loc[0]
とloc[1]
」と説明されている部分が、コード上でもloc
という名前で明確に示されることで、開発者がドキュメントとコードを行き来する際の理解がスムーズになります。
関連リンク
- Go Issue #2953: regexp: document FindStringIndex's return value as
loc
- Go CL 5653051: regexp: name result parameters referenced from docs