Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 19383] ファイルの概要

このコミットは、Go言語の公式仕様書であるdoc/go_spec.htmlファイルに対する変更です。具体的には、Goの「生文字列リテラル(raw string literals)」における改行文字(newline)とキャリッジリターン文字(carriage return)の扱いに関する記述を明確にすることを目的としています。

コミット

このコミットは、Go言語の仕様書における生文字列リテラルの挙動に関する曖昧さを解消し、特に改行文字の扱いについて明示的な記述を追加しています。これにより、Go言語のユーザーやコンパイラ実装者が、生文字列リテラル内で改行文字がどのように扱われるかを正確に理解できるようになります。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/2a627da326089dcbe9e77cdc30a3a823a1c6689a

元コミット内容

spec: clarify that newlines are kept in raw string literals

Fixes #8007.

LGTM=r
R=gri, r
CC=golang-codereviews
https://golang.org/cl/91510044

変更の背景

Go言語には、通常の文字列リテラル(interpreted string literals)と生文字列リテラル(raw string literals)の2種類があります。通常の文字列リテラルでは、バックスラッシュ(\)を用いたエスケープシーケンスが解釈されますが、生文字列リテラルでは、引用符(``)で囲まれた文字列がそのままの形で解釈されます。

このコミットが行われる前は、Goの仕様書において、生文字列リテラル内の改行文字の扱いについて明示的な記述が不足していました。特に、キャリッジリターン文字(\r)が生文字列リテラルの値から破棄されるという記述はあったものの、改行文字(\n)が保持されるのか、あるいは他の特殊な扱いを受けるのかが不明瞭でした。

この曖昧さは、Go言語のコンパイラ実装や、Goコードを解析するツール、あるいはGo言語を学習する開発者にとって混乱の原因となる可能性がありました。Issue #8007は、この仕様の曖昧さを指摘し、明確化を求めたものです。このコミットは、その問題に対応するために行われました。

前提知識の解説

文字列リテラル (String Literals)

Go言語における文字列リテラルは、プログラム内で固定の文字列値を表現する方法です。Goには主に2種類の文字列リテラルがあります。

  1. 解釈済み文字列リテラル (Interpreted String Literals):

    • ダブルクォーテーション(")で囲まれます。
    • バックスラッシュ(\)で始まるエスケープシーケンス(例: \nで改行、\tでタブ、\"でダブルクォーテーション自体)が解釈されます。
    • 改行文字を直接含めることはできません(エスケープシーケンスとして\nを使用する必要があります)。

    例: "Hello\nWorld"

  2. 生文字列リテラル (Raw String Literals):

    • バッククォーテーション(``)で囲まれます。
    • バックスラッシュを含むすべての文字が文字通りに解釈されます。エスケープシーケンスは解釈されません。
    • 複数行にわたる文字列を記述でき、リテラル内に含まれる改行文字はそのまま文字列の値として保持されます。
    • ただし、キャリッジリターン文字(\r)は特殊な扱いを受けます。

    例:

    `This is a
    multi-line
    string.`
    

    この場合、文字列の値は "This is a\nmulti-line\nstring." となります。

改行文字 (Newline) とキャリッジリターン文字 (Carriage Return)

  • 改行文字 (Newline, \n):

    • ASCIIコードではLF (Line Feed) とも呼ばれます。
    • カーソルを次の行の同じ桁位置に移動させます。
    • Unix系システム(Linux, macOSなど)では、行の終わりを示す標準的な文字です。
  • キャリッジリターン文字 (Carriage Return, \r):

    • ASCIIコードではCR (Carriage Return) とも呼ばれます。
    • カーソルを行の先頭に移動させます。
    • 歴史的にはタイプライターのキャリッジを戻す動作に由来します。
    • Windowsシステムでは、行の終わりは\r\n(CRLF)の組み合わせで表現されます。

Goの生文字列リテラルでは、Windows環境で作成されたファイルなどで見られる\r\nの組み合わせを考慮し、\rを破棄することで、異なるOS環境間での一貫した文字列処理を保証しています。これにより、生文字列リテラルが主にパスや正規表現、複数行のテキストブロックなど、文字通りの内容が重要な場面で利用される際に、プラットフォーム間の差異による予期せぬ挙動を防ぐことができます。

技術的詳細

このコミットの技術的な核心は、Go言語の仕様書における記述の正確性と明確性の向上にあります。変更前は、生文字列リテラルに関する記述が以下のようでした。

string composed of the uninterpreted (implicitly UTF-8-encoded) characters between the quotes; in particular, backslashes have no special meaning and the string may contain newlines. Carriage returns inside raw string literals are discarded from the raw string value.

この記述では、「文字列は改行を含むことができる」と述べつつも、「キャリッジリターンは破棄される」と続いています。この表現は、改行文字(\n)とキャリッジリターン文字(\r)の扱いが異なることを示唆していますが、\nが明示的に「保持される」とは書かれていませんでした。そのため、\rが破棄されるのと同様に、\nも何らかの形で処理されるのではないかという誤解を生む可能性がありました。

今回の変更では、Carriage returns inside raw string literalsという部分をCarriage return characters ('\r') inside raw string literalsと具体的に('\r')を追記することで、破棄されるのがキャリッジリターン文字に限定されることをより明確にしています。これにより、生文字列リテラル内の改行文字(\n)は、その文字通りの意味で文字列値にそのまま含まれることが暗黙的にではなく、より明確に示唆されるようになりました。

この変更は、Go言語のコンパイラやツールが、生文字列リテラルを処理する際の挙動を統一し、開発者が期待する通りの結果を得られるようにするために重要です。特に、正規表現やJSON、XMLなどの複数行にわたるテキストデータを生文字列リテラルで扱う場合、改行文字が正確に保持されることは不可欠です。

コアとなるコードの変更箇所

変更はdoc/go_spec.htmlファイルの一箇所のみです。

--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -471,7 +471,7 @@ string composed of the uninterpreted (implicitly UTF-8-encoded) characters
 between the quotes;
 in particular, backslashes have no special meaning and the string may
 contain newlines.
-Carriage returns inside raw string literals
+Carriage return characters ('\r') inside raw string literals
 are discarded from the raw string value.
 </p>
 <p>

コアとなるコードの解説

変更された行は、Go言語の仕様書における生文字列リテラルに関する説明の一部です。

  • 変更前: Carriage returns inside raw string literals
  • 変更後: Carriage return characters ('\r') inside raw string literals

この変更は、単語の追加と記号の挿入という非常に小さなものですが、その意味するところは大きいです。

  1. charactersの追加: 「Carriage returns」という抽象的な表現から、「Carriage return characters」とすることで、それが特定の文字(\r)であることをより明確にしています。
  2. ('\r')の追加: これが最も重要な変更点です。明示的に('\r')と記述することで、破棄されるのがASCII/Unicodeにおけるキャリッジリターン文字であることを疑いの余地なく示しています。これにより、生文字列リテラル内の他の改行文字(例えば\n)が破棄されることはなく、そのまま保持されるというGoの仕様がより明確になります。

この修正により、Goの仕様書は、生文字列リテラルが「バックスラッシュに特別な意味はなく、改行を含むことができる」という一般的なルールに加え、「ただし、キャリッジリターン文字(\r)は値から破棄される」という例外的なルールを、より正確かつ誤解の余地なく伝達できるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • GitHubのコミット履歴
  • Go言語のIssueトラッカー
  • Go言語のコードレビューシステム (Gerrit)
  • ASCIIコードおよび文字エンコーディングに関する一般的な知識
  • プログラミング言語における文字列リテラルの概念に関する一般的な知識
  • Go言語の生文字列リテラルに関する一般的な解説記事 (Web検索による)
  • Go言語の仕様書原文