[インデックス 18580] ファイルの概要
このコミットは、Go言語のツールチェインの一部であるcmd/pack
のテストコードにおけるバグ修正を目的としています。具体的には、TestHello
というテスト関数内で使用されている正規表現が、Plan 9オペレーティングシステム上でのビルド時に問題を引き起こすため、その正規表現を修正しています。この修正により、Plan 9環境でのGoのビルドの堅牢性が向上します。
コミット
commit 00b76713a7ba9182e9dfc29dcc37e94d000703b8
Author: Rob Pike <r@golang.org>
Date: Wed Feb 19 16:12:05 2014 -0800
cmd/pack: another attempt to fix the build for TestHello
Plan 9 uses single quotes, not double quotes. I should have known.
LGTM=bradfitz
R=bradfitz
CC=golang-codereviews
https://golang.org/cl/66240043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/00b76713a7ba9182e9dfc29dcc37e94d000703b8
元コミット内容
cmd/pack
: TestHelloのビルドを修正する別の試み
Plan 9はダブルクォートではなくシングルクォートを使用する。知っておくべきだった。
LGTM=bradfitz R=bradfitz CC=golang-codereviews https://golang.org/cl/66240043
変更の背景
このコミットの背景には、Go言語のビルドシステムが様々なオペレーティングシステム(OS)に対応する必要があるという課題があります。特に、Go言語の初期開発に深く関わったRob Pike氏が言及しているように、Plan 9というOS環境での互換性が問題となっていました。
TestHello
というテストは、go env
コマンドの出力を解析し、GOCHAR
という環境変数の値を抽出しています。このGOCHAR
の値は、Goのコンパイラがターゲットとするアーキテクチャを示す文字(例: 8
for amd64, 6
for 386)であり、ビルドプロセスにおいて重要な役割を果たします。
問題は、go env
コマンドが環境変数の値を引用符で囲んで出力する際に、OSによって使用する引用符の種類が異なる点にありました。一般的なUnix系システム(Linux, macOSなど)ではダブルクォート("
)が使われることが多いのに対し、Plan 9ではシングルクォート('
)が使われるという特性がありました。
元の正規表現はダブルクォートのみを想定していたため、Plan 9環境でgo env
の出力がシングルクォートで囲まれている場合、正規表現がマッチせず、テストが失敗していました。このコミットは、このOS間の引用符の違いを吸収し、Plan 9上でもテストが正しく動作するようにするための修正です。Rob Pike氏のコメント「知っておくべきだった」は、Plan 9のこの特性がGo開発者にとっては既知であるべきだったという自戒の念を示しています。
前提知識の解説
cmd/pack
cmd/pack
は、Go言語の初期のツールチェインの一部であり、主にアーカイブファイル(.a
ファイル)を操作するためのコマンドでした。Goのビルドプロセスにおいて、コンパイルされたオブジェクトファイルやライブラリをまとめるために使用されていました。しかし、Go 1.5以降、ビルドシステムが変更され、cmd/pack
はgo tool pack
として内部的に利用される形になり、最終的にはGo 1.10で削除されました。このコミットが行われた2014年時点では、まだGoの標準ツールとして存在していました。
go env
コマンド
go env
コマンドは、Goの環境変数の値を表示するために使用されます。例えば、GOPATH
、GOROOT
、GOOS
(オペレーティングシステム)、GOARCH
(アーキテクチャ)などのGo関連の環境設定を確認できます。このコマンドの出力は、スクリプトやツールがGoのビルド環境をプログラム的に理解するために利用されることがあります。
正規表現 (Regular Expressions)
正規表現は、文字列のパターンを記述するための強力なツールです。このコミットでは、Goのregexp
パッケージが使用されており、特定の文字列パターン(この場合はGOCHAR
環境変数の出力形式)を検索・抽出するために利用されています。正規表現の構文には、特定の文字(例: .
は任意の一文字、*
は直前の文字の0回以上の繰り返し、?
は直前の文字の0回または1回の繰り返し)や、文字クラス(例: \s
は空白文字、\w
は単語文字)などがあります。
Plan 9
Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Unixの設計思想をさらに推し進め、すべてのリソース(ファイル、デバイス、ネットワークサービスなど)をファイルシステムとして表現するという特徴を持っています。Go言語の開発者の一部(Rob Pike氏、Ken Thompson氏など)はPlan 9の開発にも深く関わっており、Go言語の設計思想にもPlan 9の影響が見られます。Plan 9は、その独特な設計と哲学から、特定の引用符の扱いなど、一般的なUnix系OSとは異なる挙動を示すことがあります。
技術的詳細
このコミットの技術的な核心は、正規表現の修正にあります。
元の正規表現: `\s*GOCHAR=\"?(\w)\"?`
修正後の正規表現: `\s*GOCHAR=[\'\"]?(\w)[\'\"]?`
この変更のポイントは、GOCHAR
の値が囲まれている引用符を、ダブルクォート("
)だけでなくシングルクォート('
)も許容するようにした点です。
\"?
から[\'\"]?
への変更:- 元の正規表現では、
GOCHAR=
の後に続く引用符として、エスケープされたダブルクォート\"
が0回または1回出現すること(?
)を期待していました。 - 修正後の正規表現では、
[\'\"]
という文字クラスが導入されています。これは「シングルクォート('
)またはダブルクォート("
)のいずれか」を意味します。この文字クラスの後に?
が付くことで、「シングルクォートまたはダブルクォートのいずれかが0回または1回出現する」というパターンにマッチするようになります。
- 元の正規表現では、
これにより、go env
の出力がGOCHAR="8"
のような形式でも、GOCHAR='8'
のような形式でも、正規表現が正しく8
という文字をキャプチャできるようになりました。この修正は、異なるOS環境(特にPlan 9)での互換性を確保するために不可欠でした。
コアとなるコードの変更箇所
--- a/src/cmd/pack/pack_test.go
+++ b/src/cmd/pack/pack_test.go
@@ -193,7 +193,7 @@ func TestHello(t *testing.T) {
}\n
out := run("go", "env")
- re, err := regexp.Compile(`\s*GOCHAR=\"?(\w)\"?`)
+ re, err := regexp.Compile(`\s*GOCHAR=[\'\"]?(\w)[\'\"]?`)
if err != nil {
t.Fatal(err)
}
コアとなるコードの解説
変更はsrc/cmd/pack/pack_test.go
ファイルのTestHello
関数内の一行に限定されています。
TestHello
関数は、Goのビルド環境をテストするために、go env
コマンドを実行し、その出力からGOCHAR
環境変数の値を抽出しています。
元のコード:
re, err := regexp.Compile(`\s*GOCHAR=\"?(\w)\"?`)
この行では、regexp.Compile
関数を使って正規表現をコンパイルしています。この正規表現は、行頭の空白文字(\s*
)に続き、GOCHAR=
という文字列、そしてオプションのダブルクォート(\"?
)があり、その後に単語文字(\w
)が1つ(これがキャプチャグループ(\w)
)、そして再びオプションのダブルクォート(\"?
)が続くパターンにマッチします。
修正後のコード:
re, err := regexp.Compile(`\s*GOCHAR=[\'\"]?(\w)[\'\"]?`)
この修正では、正規表現の\"?
の部分が[\'\"]?
に置き換えられました。
[
と]
は文字クラスを定義します。\'
はシングルクォート文字そのものを表します(正規表現リテラル内ではエスケープ不要ですが、Goの文字列リテラル内ではエスケープが必要な場合があります。ここではバッククォート文字列なので不要ですが、慣例的にエスケープされている可能性もあります)。\"
はダブルクォート文字そのものを表します。
したがって、[\'\"]
は「シングルクォートまたはダブルクォートのいずれか」にマッチします。この変更により、GOCHAR
の値がシングルクォートで囲まれていても、ダブルクォートで囲まれていても、正規表現が正しくマッチし、GOCHAR
の値((\w)
でキャプチャされる部分)を抽出できるようになりました。これにより、Plan 9環境でのテストの失敗が解消されました。
関連リンク
- Go言語の公式ドキュメント: https://golang.org/doc/
- Go言語の
regexp
パッケージ: https://pkg.go.dev/regexp - Plan 9 from Bell Labs: https://9p.io/plan9/
参考にした情報源リンク
- Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/
go env
コマンドに関する情報 (Go公式ドキュメント): https://golang.org/cmd/go/#hdr-Print_Go_environment_information- Plan 9の引用符の慣習に関する一般的な情報 (Web検索)
cmd/pack
の歴史とGo 1.5での変更に関する情報 (Web検索)- Go 1.10での
cmd/pack
の削除に関する情報 (Web検索)