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

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

このコミットは、Go言語の仕様書(doc/go_spec.html)に対する変更であり、Goの「raw string literal」(生文字列リテラル)におけるキャリッジリターン(\r)の扱いを明確にするものです。具体的には、raw string literal内に含まれるキャリッジリターンが、最終的な文字列の値から破棄されるように仕様が変更されました。

コミット

commit c26ca912e500bd0e681cfda366d3b69f8769c9c2
Author: Rob Pike <r@golang.org>
Date:   Wed Dec 14 21:52:41 2011 -0800

    spec: skip carriage returns in raw literals
    
    This change guarantees that whether the line ending convention
    when the source is created includes carriage returns is irrelevant
    to the value of the string. See issue 680.
    
    The compilers do not yet implement this.
    
    R=golang-dev, adg, r, gri, rsc, iant
    CC=golang-dev
    https://golang.org/cl/5491043

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

https://github.com/golang/go/commit/c26ca912e500bd0e681cfda366d3b69f8769c9c2

元コミット内容

このコミットの目的は、Goの仕様において、raw string literal内のキャリッジリターンをスキップすることです。これにより、ソースコードが作成された際の改行コードの慣習(CRLFやLFなど)が、文字列の値に影響を与えないことが保証されます。これは、GoのIssue 680に対応するものです。コミット時点では、コンパイラはこの変更をまだ実装していませんでした。

変更の背景

この変更は、Go言語のIssue 680「deal with files using \r\n or \r line endings」に関連しています。異なるオペレーティングシステム(OS)では、テキストファイルの改行コードが異なります。

  • Unix/Linux: ラインフィード(LF, \n)のみを使用します。
  • Windows: キャリッジリターンとラインフィードの組み合わせ(CRLF, \r\n)を使用します。
  • 古いMac OS: キャリッジリターン(CR, \r)のみを使用します。

Goのraw string literalは、バックスラッシュのエスケープシーケンスを解釈せず、引用符間の文字をそのまま文字列の値として扱います。しかし、もしraw string literalが複数行にまたがる場合、ソースファイルに記述された改行コードがそのまま文字列に含まれてしまうと、以下のような問題が発生します。

  1. 移植性の問題: 同じGoのソースコードでも、Windowsで作成されたファイルとUnixで作成されたファイルでは、raw string literalの最終的な値が異なる可能性があります。例えば、Windowsで作成されたファイルでは\r\nが含まれ、Unixで作成されたファイルでは\nのみが含まれる、といった状況です。
  2. 予測可能性の欠如: 開発者が意図しない\r文字が文字列に含まれることで、文字列の比較や処理において予期せぬバグが発生する可能性があります。

この問題を解決するため、Goの仕様として、raw string literal内のキャリッジリターン(\r)を破棄することで、ソースファイルの改行コードに依存しない一貫した文字列値を提供することが決定されました。

前提知識の解説

GoのRaw String Literal(生文字列リテラル)

Go言語には、2種類の文字列リテラルがあります。

  1. Interpreted String Literal(解釈済み文字列リテラル): ダブルクォート(")で囲まれた文字列です。バックスラッシュ(\)で始まるエスケープシーケンス(例: \n\t\")が解釈され、対応する特殊文字に変換されます。 例: "Hello\nWorld" は "Hello" の後に改行、"World" が続く文字列になります。

  2. Raw String Literal(生文字列リテラル): バッククォート(`)で囲まれた文字列です。このリテラル内では、バックスラッシュを含むすべての文字が文字通りに解釈されます。エスケープシーケンスは処理されず、改行もそのまま文字列に含まれます。これは、正規表現、HTML、JSONなどの複数行にわたるテキストや、バックスラッシュを多用するパスなどを記述するのに非常に便利です。 例: `C:\Program Files\Go` は、C:\Program Files\Go という文字列になります。

改行コード(Line Endings)

テキストファイルにおける改行の表現方法は、OSによって異なります。

  • LF (Line Feed, \n, ASCII 10): Unix、Linux、macOS(OS X以降)で主に使用されます。
  • CRLF (Carriage Return + Line Feed, \r\n, ASCII 13 + ASCII 10): Windowsで主に使用されます。
  • CR (Carriage Return, \r, ASCII 13): 古いMac OS(Mac OS 9以前)で主に使用されました。

これらの違いは、特に異なるOS間でファイルを共有したり、バージョン管理システムを使用したりする際に問題となることがあります。

技術的詳細

このコミットによる技術的な変更は、Go言語の仕様書に「raw string literal内でキャリッジリターンが破棄される」というルールを追加することです。

具体的には、raw string literalがソースコード上で複数行にわたって記述され、そのソースファイルがCRLF(\r\n)の改行コードを使用している場合、文字列リテラルには\r\nの両方が含まれることになります。しかし、この仕様変更により、Goコンパイラはraw string literalを解析する際に、\r文字を無視し、\nのみを文字列の値として保持するようになります。

これにより、以下のような効果が期待されます。

  • プラットフォーム非依存性: どのようなOSでソースファイルが作成されたとしても、raw string literalの最終的な値は一貫したものになります。例えば、Windowsで作成されたGoソースファイル内のraw string literalと、Linuxで作成された同じ内容のGoソースファイル内のraw string literalは、全く同じ文字列値を持つことになります。
  • 予測可能な挙動: 開発者は、raw string literalに意図しない\r文字が含まれることを心配する必要がなくなります。これにより、文字列の処理や比較がよりシンプルで堅牢になります。

コミットメッセージには「The compilers do not yet implement this.」と明記されており、この変更はまず仕様として定義され、その後コンパイラがそれに追従して実装されるというプロセスが示されています。これは、言語仕様の変更が、実際のコンパイラの挙動に先行して行われる一般的なアプローチです。

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

このコミットによる変更は、Go言語の仕様書であるdoc/go_spec.htmlファイルに対して行われました。

--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,5 +1,5 @@
 <!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of December 13, 2011 -->
+<!-- subtitle Version of December 14, 2011 -->
 
 <!--
 TODO
@@ -454,6 +454,8 @@ back quote. The value of a raw string literal is the
 string composed of the uninterpreted characters between the quotes;
 in particular, backslashes have no special meaning and the string may
 span multiple lines.
+Carriage returns inside raw string literals
+are discarded from the raw string value.
 </p>
 <p>
 Interpreted string literals are character sequences between double

変更は主に2つの部分です。

  1. 日付の更新: 仕様書のバージョン日付が「December 13, 2011」から「December 14, 2011」に更新されています。これは、仕様書が更新されたことを示す一般的な変更です。
  2. Raw String Literalの記述の追加: Raw string literalに関する既存の段落に、新しいルールが追加されました。

コアとなるコードの解説

追加された行は以下の通りです。

+Carriage returns inside raw string literals
+are discarded from the raw string value.

この2行が、Goのraw string literalのセクションに追記されました。これにより、Goの仕様として、raw string literal内に存在するキャリッジリターン(\r)は、最終的な文字列の値から破棄されることが明確に定義されました。

この変更は、Go言語の設計哲学である「シンプルさ」と「予測可能性」を反映しています。異なる環境でGoコードを記述しても、文字列リテラルの挙動が一貫していることで、開発者はより安心してコードを書くことができます。

関連リンク

参考にした情報源リンク