[インデックス 15427] ファイルの概要
このコミットは、Go言語の標準ライブラリであるstrconv
パッケージとfmt
パッケージにおける、文字列のクォート(引用符付け)に関する挙動の明確化を目的としています。具体的には、strconv.CanBackquote
関数のレポート内容と、fmt
パッケージの書式指定子%#q
の動作説明が修正されています。
コミット
commit 4692711d7f172ab69a9576ffbe753314755f780a
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Tue Feb 26 06:33:59 2013 +0800
strconv, fmt: clarify behavior of CanBackquote and "%#q".
Fixes #4858.
R=golang-dev, bradfitz, r, rsc
CC=golang-dev
https://golang.org/cl/7387044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4692711d7f172ab69a9576ffbe753314755f780a
元コミット内容
このコミットの元のメッセージは以下の通りです。
strconv, fmt: clarify behavior of CanBackquote and "%#q".
Fixes #4858.
これは、strconv
パッケージとfmt
パッケージにおいて、CanBackquote
関数と%#q
書式指定子の挙動を明確にすることを目的としていることを示しています。また、GoのIssue #4858を修正するものであることも明記されています。
変更の背景
このコミットは、Go言語のIssue #4858「fmt: %#q should use backquotes if possible」を修正するために行われました。このIssueでは、fmt
パッケージの%#q
書式指定子が、文字列をバッククォート(
`)で囲んで出力する際に、どのような条件でバッククォートを使用するのかが不明確であるという問題が提起されていました。
具体的には、%#q
はGoの文字列リテラル形式で値をクォートしますが、バッククォート文字列リテラル(raw string literal)はエスケープシーケンスを解釈しないため、特定の文字(特にバッククォート自身や制御文字)が含まれる場合には使用できません。しかし、既存のドキュメントではその条件が明確に記述されていませんでした。
また、strconv.CanBackquote
関数も、ある文字列がバッククォートで囲まれたGoの文字列リテラルとして有効であるかどうかを報告する関数ですが、その「有効」の定義が曖昧でした。特に、制御文字や改行を含む文字列に対する挙動がユーザーにとって直感的ではない可能性がありました。
このコミットは、これらの曖昧さを解消し、開発者がCanBackquote
と%#q
の挙動をより正確に理解できるようにするために導入されました。
前提知識の解説
このコミットの理解には、以下のGo言語の概念に関する知識が必要です。
- Goの文字列リテラル: Goには主に2種類の文字列リテラルがあります。
- 解釈済み文字列リテラル (Interpreted string literal): ダブルクォート(
"
)で囲まれた文字列で、バックスラッシュ(\
)によるエスケープシーケンス(例:\n
、\t
、\"
)が解釈されます。 - 生文字列リテラル (Raw string literal): バッククォート(
- 解釈済み文字列リテラル (Interpreted string literal): ダブルクォート(
fmt
パッケージ: Go言語のフォーマットI/Oを扱うパッケージです。fmt.Printf
などの関数を使って、様々な型の値を指定された書式で文字列に変換して出力します。- 書式指定子:
fmt
パッケージでは、%v
(デフォルト)、%s
(文字列)、%q
(クォートされた文字列)など、様々な書式指定子が提供されています。 - フラグ: 書式指定子には、追加の挙動を制御するためのフラグを付加できます。例えば、
#
フラグは「代替形式」を意味し、型に応じた特別な書式を適用します。%#q
の場合、可能な場合はバッククォートで囲まれた文字列として出力しようとします。
- 書式指定子:
strconv
パッケージ: 文字列と基本的なデータ型(数値、真偽値など)との間の変換を扱うパッケージです。strconv.CanBackquote
関数: この関数は、与えられた文字列がバッククォートで囲まれたGoの文字列リテラルとして表現可能かどうかを判定します。
技術的詳細
このコミットは、fmt
パッケージのドキュメントとstrconv.CanBackquote
関数の実装およびドキュメントの両方を修正することで、挙動の明確化を図っています。
fmt
パッケージのドキュメント修正 (src/pkg/fmt/doc.go
)
変更前は、%#q
のドキュメントが「print a raw (backquoted) string if possible for %q (%#q);」と記述されていました。これは「可能であれば生(バッククォートで囲まれた)文字列を出力する」という意味ですが、「可能」の具体的な条件が不明確でした。
変更後は、「for %q, print a raw (backquoted) string if strconv.CanBackquote returns true;」と修正されました。これにより、%#q
がバッククォート文字列を使用する条件が、strconv.CanBackquote
関数の戻り値に依存することが明確に示されました。これは、fmt
パッケージの挙動がstrconv
パッケージの定義に準拠することを意味し、一貫性が向上します。
strconv.CanBackquote
関数のドキュメント修正 (src/pkg/strconv/quote.go
)
変更前は、CanBackquote
関数のドキュメントが「CanBackquote returns whether the string s would be a valid Go string literal if enclosed in backquotes.」と記述されていました。これも「有効なGo文字列リテラル」の定義が曖昧でした。
変更後は、「CanBackquote reports whether the string s can be represented unchanged as a single-line backquoted string without control characters other than space and tab.」と修正されました。この新しいドキュメントは、CanBackquote
が以下の条件を満たす場合にtrue
を返すことを明確にしています。
- 変更なしで表現可能: 文字列の内容がそのままバッククォート内に収まること。
- 単一行: 文字列が改行を含まないこと。
- 特定の制御文字以外を含まない: スペース(
\t
)以外の制御文字(ASCII値が - バッククォート文字を含まない: 文字列自身がバッククォート(
この修正により、CanBackquote
の挙動がより厳密に定義され、特に制御文字や改行を含む文字列に対する期待される結果が明確になりました。これにより、開発者はCanBackquote
の戻り値に基づいて、文字列をバッククォートで安全に表現できるかどうかを判断できるようになります。
コアとなるコードの変更箇所
src/pkg/fmt/doc.go
--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -74,7 +74,8 @@
- pad with spaces on the right rather than the left (left-justify the field)
# alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
0X for hex (%#X); suppress 0x for %p (%#p);
- print a raw (backquoted) string if possible for %q (%#q);
+ for %q, print a raw (backquoted) string if strconv.CanBackquote
+ returns true;
write e.g. U+0078 'x' if the character is printable for %U (%#U).
' ' (space) leave a space for elided sign in numbers (% d);
put spaces between bytes printing strings or slices in hex (% x, % X)
src/pkg/strconv/quote.go
--- a/src/pkg/strconv/quote.go
+++ b/src/pkg/strconv/quote.go
@@ -139,8 +139,9 @@ func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
return append(dst, QuoteRuneToASCII(r)...)
}
-// CanBackquote returns whether the string s would be
-// a valid Go string literal if enclosed in backquotes.
+// CanBackquote reports whether the string s can be represented
+// unchanged as a single-line backquoted string without control
+// characters other than space and tab.
func CanBackquote(s string) bool {
for i := 0; i < len(s); i++ {
if (s[i] < ' ' && s[i] != '\t') || s[i] == '`' {
コアとなるコードの解説
src/pkg/fmt/doc.go
の変更
この変更は、fmt
パッケージのドキュメンテーションコメント内の%#q
書式指定子の説明を更新しています。
- 変更前:
print a raw (backquoted) string if possible for %q (%#q);
- 「可能であれば生(バッククォートで囲まれた)文字列を出力する」という記述で、「可能」の条件が不明確でした。
- 変更後:
for %q, print a raw (backquoted) string if strconv.CanBackquote returns true;
- 「
strconv.CanBackquote
がtrue
を返す場合、生(バッククォートで囲まれた)文字列を出力する」と明確に記述されました。これにより、%#q
の挙動がstrconv.CanBackquote
の定義に直接リンクされ、一貫性と明確性が向上しました。
- 「
src/pkg/strconv/quote.go
の変更
この変更は、strconv.CanBackquote
関数のドキュメンテーションコメントを更新しています。関数の実際のロジック(ループ内の条件 (s[i] < ' ' && s[i] != '\t') || s[i] == '
'`)は変更されていませんが、そのロジックが何を意図しているのかをより正確に説明しています。
- 変更前:
CanBackquote returns whether the string s would be a valid Go string literal if enclosed in backquotes.
- 「文字列
s
がバッククォートで囲まれた場合に有効なGo文字列リテラルになるかどうかを返す」という記述で、「有効」の定義が曖昧でした。
- 「文字列
- 変更後:
CanBackquote reports whether the string s can be represented unchanged as a single-line backquoted string without control characters other than space and tab.
- 「文字列
s
が、スペースとタブ以外の制御文字を含まず、単一行のバッククォート文字列として変更なしで表現できるかどうかを報告する」と明確に記述されました。 - この新しい説明は、以下の条件を暗に示しています。
s[i] < ' ' && s[i] != '\t'
: スペース(ASCII 32)より小さい文字(制御文字)で、かつタブ(ASCII 9)ではない文字が含まれていないこと。これは、改行文字(\n
)も含まれないことを意味し、結果として「単一行」の条件を満たします。s[i] == '
'`: バッククォート文字自身が含まれていないこと。
- これにより、
CanBackquote
がtrue
を返す具体的な条件がユーザーにとって非常に明確になりました。
- 「文字列
これらの変更は、Go言語のドキュメントの正確性と、関連するパッケージ間の挙動の一貫性を高める上で重要な役割を果たしています。
関連リンク
- Go Issue #4858: https://github.com/golang/go/issues/4858
- Go CL 7387044: https://golang.org/cl/7387044
参考にした情報源リンク
- Go言語の公式ドキュメント(
fmt
パッケージ、strconv
パッケージ) - Go言語のソースコード(
src/pkg/fmt/doc.go
,src/pkg/strconv/quote.go
) - Go言語のIssueトラッカー(Issue #4858)
- Go言語のコードレビューシステム(CL 7387044)
- Go言語の文字列リテラルに関する一般的な情報源