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

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

このコミットは、Go言語の公式仕様書 doc/go_spec.html に、バイトオーダーマーク (BOM) の取り扱いに関する実装上の制限について、より明確な記述を追加するものです。具体的には、UTF-8 BOM がファイルの先頭以外に存在する場合のコンパイラの挙動について追記されています。

コミット

commit 548c65a568e14490f1a6b80e92c175e2410ddf20
Author: Rob Pike <r@golang.org>
Date:   Thu Apr 11 11:33:25 2013 -0700

    spec: add another sentence about BOMs
    Although one may argue that they should be legal, gc (at least)
    disallows byte order marks that are not the first code point
    in the file. Added a sentence to the "Implementation restriction"
    clause in the "Source code representation" section to document
    this better.
    
    Lifting this restriction (again - the rule has changed at least
    twice already) would not break any existing programs, should
    we later decide yet again to fiddle the rules about these little
    fly specks.
    
    R=golang-dev, dsymonds, gri
    CC=golang-dev
    https://golang.org/cl/8649043

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

https://github.com/golang/go/commit/548c65a568e14490f1a6b80e92c175e2410ddf20

元コミット内容

このコミットは、Go言語の仕様書に、バイトオーダーマーク (BOM) に関する追加の文言を加えるものです。Goコンパイラ(特に gc)は、ファイルの先頭以外の位置にあるBOMを許可しないという既存の挙動を、仕様書の「実装上の制限 (Implementation restriction)」セクションに明記することで、この挙動をより良く文書化することを目的としています。コミットメッセージでは、この制限を解除しても既存のプログラムには影響がないこと、そして過去にこのルールが何度か変更されてきた経緯にも触れられています。

変更の背景

Go言語のコンパイラ、特に gc は、ソースコードファイル内のバイトオーダーマーク (BOM) の扱いに特定の制約を設けていました。具体的には、UTF-8エンコードされたBOM (U+FEFF) は、ファイルの先頭にのみ存在することが許容され、それ以外の位置にあるBOMは許可されていませんでした。しかし、この挙動がGo言語の公式仕様書に明確に記述されていなかったため、開発者が混乱する可能性がありました。

このコミットの背景には、以下の点が挙げられます。

  1. 既存のコンパイラ挙動の明文化: gc コンパイラが既に持っていたBOMに関する挙動(先頭以外のBOMを許可しない)を、公式仕様書に明記することで、Go言語のソースコードの解釈に関する曖昧さを解消し、開発者に対してより明確なガイドラインを提供すること。
  2. 互換性の維持: コミットメッセージにあるように、この制限を解除しても既存のプログラムが壊れることはないものの、現在の挙動を仕様に反映させることで、将来的な変更の可能性を残しつつ、現状の安定性を保つ意図があります。
  3. 過去の経緯: コミットメッセージには「このルールは既に少なくとも2回変更されている」とあり、BOMの扱いはGo言語の初期から議論の対象となってきたことが示唆されます。このような経緯を踏まえ、現在の安定した挙動を文書化することが重要であると判断されたと考えられます。

この変更は、Go言語の仕様の正確性と完全性を高め、開発者がGoソースコードの文字エンコーディングとBOMの扱いに際して、より予測可能な環境で作業できるようにすることを目的としています。

前提知識の解説

バイトオーダーマーク (BOM)

バイトオーダーマーク (Byte Order Mark, BOM) は、Unicodeテキストファイルの先頭に付加される特殊なバイト列で、そのファイルがどのUnicodeエンコーディング(UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BEなど)でエンコードされているか、またマルチバイト文字のバイト順(エンディアン)を示すために使用されます。

  • UTF-8におけるBOM:
    • UTF-8はバイトオーダーの概念を持たないため、技術的にはBOMは不要です。UTF-8のBOMは EF BB BF という3バイトのシーケンスで表されます。
    • しかし、一部のWindowsアプリケーション(例: メモ帳)は、UTF-8ファイルを保存する際に互換性のためにBOMを付加することがあります。
    • BOMはファイルの先頭にのみ意味を持ち、それ以外の位置に現れることは通常ありません。ファイルの途中にBOMが現れると、それは通常のテキストデータの一部として扱われるか、あるいは不正な文字として扱われる可能性があります。

Go言語のソースコード表現

Go言語のソースコードは、Unicode文字のUTF-8エンコーディングで表現されます。Goの仕様では、ソースコードの文字セット、識別子、リテラルなどの規則が厳密に定義されています。

  • Goの仕様とBOM:
    • Goの仕様は、ソースコードの文字エンコーディングとしてUTF-8を要求しています。
    • 過去のGoの仕様では、BOMの扱いについていくつかの変更がありました。一般的に、GoコンパイラはBOMを無視するか、あるいは特定の条件下でのみ許可する傾向にあります。これは、BOMが不要なUTF-8において、BOMの存在がパーサーやツールチェーンに予期せぬ問題を引き起こす可能性があるためです。
    • 特に、ファイルの先頭にBOMが存在する場合、多くのツールやエディタはそれをエンコーディングのヒントとして解釈し、無視することが一般的です。しかし、ファイルの途中にBOMが存在すると、それは通常のコードポイントとして扱われるか、あるいは構文エラーを引き起こす可能性があります。

このコミットは、Goコンパイラがファイルの先頭以外のBOMをどのように扱うかという、既存の「実装上の制限」を明確にすることで、Go言語のソースコードの厳密な解釈を保証しようとするものです。

技術的詳細

このコミットは、Go言語の仕様書 doc/go_spec.html の「Source code representation」セクションにある「Implementation restriction」の項目に、以下の1文を追加することで、BOMの扱いに関するGoコンパイラの挙動を明確にしています。

追加された文言: A byte order mark may be disallowed anywhere else in the source. (バイトオーダーマークは、ソース内の他のどこでも許可されない場合があります。)

この変更の技術的な意味合いは以下の通りです。

  1. 既存の挙動の明文化: Goコンパイラ(特に gc)は、既にファイルの先頭以外の位置にあるUTF-8 BOM (U+FEFF) をエラーとして扱っていました。このコミットは、この既存の「実装上の制限」を公式仕様書に明記することで、Go言語のソースコードの解釈に関する曖昧さを排除します。
  2. BOMの厳密な解釈:
    • Goの仕様では、UTF-8エンコードされたBOM (U+FEFF) は、ソーステキストの最初のUnicodeコードポイントである場合に限り、コンパイラが無視してもよいとされています。これは、一部のツールがUTF-8ファイルにBOMを付加する慣習に対応するためです。
    • しかし、このコミットで追加された文言により、ファイルの先頭以外の位置にBOMが存在する場合、Goコンパイラはそれを許可しない(つまり、エラーとする)可能性があることが明確になります。これは、BOMがファイルのエンコーディングを示すためのものであり、ファイルの途中に現れることは意味がなく、むしろ構文解析上の問題を引き起こす可能性があるためです。
  3. 一貫性と予測可能性: この明確化により、Go言語のソースコードがBOMに関してどのように扱われるかについて、開発者はより一貫した予測可能な挙動を期待できるようになります。これにより、異なるエディタやツールで作成されたGoソースコードが、Goコンパイラによって一貫して処理されることが保証されます。
  4. 将来の柔軟性: コミットメッセージにある「Lifting this restriction... would not break any existing programs, should we later decide yet again to fiddle the rules about these little fly specks.」という記述は、この制限が将来的に変更される可能性を示唆しています。しかし、現時点では、既存のコンパイラの挙動を仕様に反映させることで、安定性を確保しています。

この変更は、Go言語の仕様の厳密性を高め、ソースコードの文字エンコーディングに関する潜在的な問題を未然に防ぐための重要なステップです。

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

変更は doc/go_spec.html ファイルに対して行われました。

--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
 <!--{
  	"Title": "The Go Programming Language Specification",
-	"Subtitle": "Version of April 3, 2013",
+	"Subtitle": "Version of April 10, 2013",
  	"Path": "/ref/spec"
 }-->
 
@@ -103,6 +103,7 @@ compiler may disallow the NUL character (U+0000) in the source text.\n Implementation restriction: For compatibility with other tools, a\n compiler may ignore a UTF-8-encoded byte order mark\n (U+FEFF) if it is the first Unicode code point in the source text.\n+A byte order mark may be disallowed anywhere else in the source.\n </p>\n 

具体的には、以下の2箇所が変更されています。

  1. 仕様書のバージョン日付の更新: - "Subtitle": "Version of April 3, 2013", + "Subtitle": "Version of April 10, 2013", これは、仕様書の内容が更新されたことに伴う、単なる日付の変更です。

  2. BOMに関する実装制限の追加: Implementation restriction: For compatibility with other tools, a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF) if it is the first Unicode code point in the source text. +A byte order mark may be disallowed anywhere else in the source. </p> この部分に、A byte order mark may be disallowed anywhere else in the source. という新しい文が追加されました。

コアとなるコードの解説

追加された行 A byte order mark may be disallowed anywhere else in the source. は、Go言語の仕様書における「実装上の制限 (Implementation restriction)」のセクションに位置しています。このセクションは、Go言語のコンパイラが、仕様で定義された範囲内で、特定の挙動をどのように実装してもよいか、あるいは特定の制約を課してもよいかを示すものです。

この文が追加される前の記述は以下の通りでした。 「互換性のために、コンパイラは、UTF-8エンコードされたバイトオーダーマーク (U+FEFF) がソーステキストの最初のUnicodeコードポイントである場合に、それを無視してもよい。」

この既存の記述は、ファイルの先頭にあるBOMの扱いについて、コンパイラに柔軟性を持たせていました。しかし、ファイルの途中にBOMが存在する場合の挙動については明示されていませんでした。

今回追加された A byte order mark may be disallowed anywhere else in the source. という文は、このギャップを埋めるものです。これにより、以下の点が明確になります。

  • ファイルの先頭以外のBOMは許可されない可能性がある: この文は、ファイルの先頭以外の位置にBOMが存在する場合、Goコンパイラがそれを許可しない(つまり、エラーとして扱う)可能性があることを明確に示しています。これは「may be disallowed」という表現から、コンパイラの実装によってはエラーとしない可能性も示唆していますが、一般的なGoコンパイラ(特に gc)はこれをエラーとして扱います。
  • 厳密なソースコードの解釈: Go言語は、ソースコードの厳密な解釈を重視します。BOMは通常、ファイルのエンコーディングを示すためにファイルの先頭にのみ使用されるべきものです。ファイルの途中にBOMが存在することは、意図しない文字として解釈されたり、構文解析エラーを引き起こしたりする可能性があるため、これを許可しないことで、ソースコードの健全性を保ちます。
  • 開発者へのガイドライン: この記述により、Go言語の開発者は、ソースコードファイルにBOMを含める場合は、必ずファイルの先頭にのみ配置し、それ以外の位置には含めないようにすべきであるという明確なガイドラインを得ることができます。

要するに、この変更は、Go言語のソースコードにおけるBOMの扱いに関するコンパイラの既存の挙動を仕様に反映させ、開発者に対してより明確で厳密なルールを提供することを目的としています。

関連リンク

  • Gerrit Change-Id: https://golang.org/cl/8649043 (これはGoプロジェクトのコードレビューシステムであるGerritの変更リストへのリンクです。コミットの詳細な議論やレビュープロセスを確認できます。)

参考にした情報源リンク