[インデックス 116] ファイルの概要
このコミットでは、Go言語のテストスイート内の2つのファイルが変更されています。
test/golden.out
: テストの期待される出力(ゴールデンファイル)を定義するファイルです。このファイルは、特定のテストケースが生成する出力と照合され、テストの合否を判断するために使用されます。test/string_lit.go
: Go言語の文字列リテラルに関する挙動をテストするためのソースコードファイルです。様々な種類の文字列リテラルやエスケープシーケンスの解釈が正しく行われるかを確認します。
コミット
このコミットは、Go言語のテストスイートにおける誤ったテストケースを修正することを目的としています。具体的には、文字列リテラル内のエスケープシーケンスの解釈に関するテストが、Go言語の仕様に合致しない形でエラーを報告していたため、その誤りを訂正しています。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5e77b0a82e2f8d0b01f268150f7f93c3d9534175
元コミット内容
fix erroneous test
SVN=121554
変更の背景
Go言語の初期開発段階において、文字列リテラル内のエスケープシーケンスの解釈に関するテストが、言語仕様と異なる振る舞いを期待していました。具体的には、シングルクォートのエスケープシーケンス \'
が「未知のエスケープシーケンス」として誤って報告されることを期待するテスト出力が test/golden.out
に含まれていました。しかし、Go言語の文字列リテラルにおいて、シングルクォート \'
は特別なエスケープシーケンスとしては定義されていません。このコミットは、この誤ったテストの期待値を修正し、Go言語の文字列リテラルに関する正しい挙動を反映させるために行われました。
前提知識の解説
Go言語の文字列リテラル
Go言語には主に2種類の文字列リテラルがあります。
-
解釈される文字列リテラル (Interpreted String Literals):
- ダブルクォート
"
で囲まれた文字列です。 - バックスラッシュ
\
を用いたエスケープシーケンスが解釈されます。 - 例:
"Hello\nWorld"
は改行を含む文字列になります。
- ダブルクォート
-
生文字列リテラル (Raw String Literals):
- バッククォート
`
で囲まれた文字列です。 - エスケープシーケンスは解釈されず、バックスラッシュを含む全ての文字がそのまま文字列の一部として扱われます。
- 複数行にわたる文字列を記述するのに便利です。
- 例:
`C:\Program Files\Go`
はバックスラッシュがそのまま含まれる文字列になります。
- バッククォート
Go言語のエスケープシーケンス
解釈される文字列リテラル内で使用できる標準的なエスケープシーケンスには以下のようなものがあります。
\a
: アラート (ベル)\b
: バックスペース\f
: フォームフィード\n
: 改行 (ラインフィード)\r
: キャリッジリターン\t
: 水平タブ\v
: 垂直タブ\\
: バックスラッシュ\"
: ダブルクォート\ooo
: 8進数表記 (例:\000
はヌル文字)\xhh
: 16進数表記 (例:\x00
)\uhhhh
: Unicodeコードポイント (UTF-16) (例:\u0123
)\Uhhhhhhhh
: Unicodeコードポイント (UTF-32) (例:\U0123ABCD
)
重要な点として、Go言語の文字列リテラルでは、シングルクォート \'
は標準のエスケープシーケンスとしては定義されていません。シングルクォートは、文字リテラル(runeリテラル)内で使用される場合にのみ、エスケープする必要がある場合があります(例: '\''
)。しかし、文字列リテラル内では、シングルクォートは特別な意味を持たないため、エスケープする必要はありません。
技術的詳細
このコミットは、Go言語のコンパイラが文字列リテラルをどのようにパースし、エスケープシーケンスをどのように解釈するかという、言語の基本的な構文規則に深く関連しています。
test/golden.out
ファイルは、Go言語のテストフレームワークにおいて「ゴールデンファイル」として機能します。これは、テスト対象のプログラム(この場合はGoコンパイラやパーサー)が生成する出力が、事前に定義されたこのファイルの内容と完全に一致することを期待するものです。もし出力が一致しなければ、テストは失敗します。
このコミット以前は、test/string_lit.go
内の文字列リテラル \"\\a\\b\\f\\n\\r\\t\\v\\\\\\\'\\\"\"
がコンパイルされた際に、\'
の部分が「未知のエスケープシーケンス」としてエラーを発生させ、そのエラーメッセージが test/golden.out
に記録されていました。しかし、Go言語の仕様では、文字列リテラル内でシングルクォートをエスケープする必要はなく、\'
は有効なエスケープシーケンスではありません。したがって、このエラーはコンパイラが誤って \'
を特別なエスケープシーケンスとして扱おうとした結果、またはテストの期待値が誤っていた結果として発生していました。
このコミットでは、test/string_lit.go
から \'
を削除することで、テストがGo言語の正しい文字列リテラルの解釈に合致するように修正されました。これにより、test/golden.out
からも対応するエラーメッセージの行が削除され、テストが正しくパスするようになりました。これは、Go言語の文字列リテラルにおけるエスケープシーケンスの厳密な定義を反映した修正であり、言語の安定性と正確性を保証する上で重要な変更です。
コアとなるコードの変更箇所
diff --git a/test/golden.out b/test/golden.out
index 935e5be6e0..4ea3036e73 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -53,7 +53,6 @@ BUG: known to fail incorrectly
=========== ./string_lit.go
string_lit.go:5: syntax error
string_lit.go:12: unknown escape sequence: \\\
-string_lit.go:12: unknown escape sequence: '
BUG: known to fail incorrectly
=========== ./switch.go
diff --git a/test/string_lit.go b/test/string_lit.go
index 1e725354b2..1b106cdadf 100644
--- a/test/string_lit.go
+++ b/test/string_lit.go
@@ -14,7 +14,7 @@ func main() {
"a",
"ä",
"本",
- "\\a\\b\\f\\n\\r\\t\\v\\\\\\\'\\\"\",
+ "\\a\\b\\f\\n\\r\\t\\v\\\\\\\"\",
"\\000\\123\\x00\\xca\\xFE\\u0123\\ubabe\\U0123ABCD\\Ucafebabe",
``,
コアとなるコードの解説
test/golden.out
の変更
- string_lit.go:12: unknown escape sequence: '
: この行がtest/golden.out
から削除されました。これは、test/string_lit.go
の12行目にある文字列リテラルが、以前は\'
という「未知のエスケープシーケンス」のためにエラーを発生させることが期待されていたことを示しています。この行の削除は、もはやこのエラーが発生しないことをテストが期待していることを意味します。
test/string_lit.go
の変更
- "\\a\\b\\f\\n\\r\\t\\v\\\\\\\'\\\"\",
+ "\\a\\b\\f\\n\\r\\t\\v\\\\\\\"\",
この変更は、文字列リテラルから \'
エスケープシーケンスを削除しています。
- 変更前:
...\\\\\\\'\\\"\"
\\
: バックスラッシュ自身をエスケープ\'
: シングルクォートをエスケープ(これはGoの文字列リテラルでは不要であり、誤り)\"
: ダブルクォートをエスケープ
- 変更後:
...\\\\\\\"\"
\\
: バックスラッシュ自身をエスケープ\"
: ダブルクォートをエスケープ
この修正により、test/string_lit.go
はGo言語の正しい文字列リテラルの構文に準拠するようになりました。結果として、コンパイラはもはや \'
を未知のエスケープシーケンスとして報告せず、test/golden.out
から対応するエラーメッセージを削除することが可能になりました。
関連リンク
- Go言語仕様 (The Go Programming Language Specification):
参考にした情報源リンク
この解説は、Go言語の公式ドキュメント、特に言語仕様の文字列リテラルに関するセクション、および一般的なプログラミング言語におけるエスケープシーケンスの概念に基づいています。特定の外部記事やブログを参照したものではありません。