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

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

コミット

このコミットは、Go言語の仕様書 (doc/go_spec.html) を更新し、UTF-8エンコードされたバイトオーダーマーク (BOM: Byte Order Mark) の扱いに関する新たな実装上の制約を追加するものです。具体的には、文字列リテラルおよびルーンリテラル以外のソースコード中に存在するBOMを、Goコンパイラが無視してもよいという規定が盛り込まれました。これは、他のツールとの互換性を高めるための変更です。

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

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

元コミット内容

commit afac01df48189013e62f5d2285b8e3b6d38e3f44
Author: Rob Pike <r@golang.org>
Date:   Thu Sep 6 10:37:13 2012 -0700

    spec: ignore BOMS outside of string and rune literals.
    Happy Birthday UTF-8.
    
    R=golang-dev, rsc, 0xjnml
    CC=golang-dev
    https://golang.org/cl/6506083

変更の背景

この変更の背景には、UTF-8エンコーディングにおけるバイトオーダーマーク (BOM) の扱いの複雑さがあります。UTF-8はバイトオーダーに依存しないエンコーディングであるため、BOMは必須ではありません。しかし、特にWindows環境で作成されたテキストエディタなど、一部のツールはUTF-8ファイルを保存する際にBOMを自動的に付加する場合があります。

このようなBOMが付加されたソースコードファイルが、BOMを予期しないコンパイラやツールによって処理されると、構文エラー、予期せぬ文字の挿入、スクリプトの実行失敗など、様々な問題を引き起こす可能性があります。Go言語のコンパイラも、BOMを予期しない場合に問題が発生する可能性がありました。

このコミットは、Goコンパイラがソースコード中のBOMを(文字列リテラルやルーンリテラル内を除いて)無視することを許可することで、他のツールとの互換性を向上させ、開発者がBOMの有無を気にすることなくGoのソースコードを扱えるようにすることを目的としています。コミットメッセージにある「Happy Birthday UTF-8」は、UTF-8の誕生日(1992年9月)に合わせたジョークであり、UTF-8の普及とそれに伴う互換性問題への対応を示唆しています。

前提知識の解説

UTF-8 (Unicode Transformation Format - 8-bit)

UTF-8は、Unicode文字を可変長のバイトシーケンスでエンコードする文字エンコーディング方式です。ASCII文字は1バイトで表現され、非ASCII文字は2バイト以上で表現されます。インターネット上で最も広く使用されている文字エンコーディングであり、多言語対応に不可欠です。

BOM (Byte Order Mark)

BOMは、Unicodeテキストファイルの先頭に付加される特殊なバイトシーケンスで、そのファイルがどのUnicodeエンコーディング(UTF-8, UTF-16, UTF-32など)でエンコードされているか、またバイトオーダー(ビッグエンディアンかリトルエンディアンか)を示すために使用されます。 UTF-8のBOMは EF BB BF の3バイトシーケンスです。UTF-8はバイトオーダーに依存しないため、UTF-8におけるBOMはエンコーディングの識別子としての役割しか持ちません。しかし、多くのUnix系ツールやプログラミング言語のパーサーはBOMを予期せず、これを通常の文字として扱ってしまうため、問題を引き起こすことがあります。

文字列リテラル (String literals)

プログラミング言語において、ソースコード中に直接記述される文字列の定数です。Go言語では、ダブルクォート (") またはバッククォート (`) で囲まれたシーケンスとして表現されます。例: "Hello, World!"。文字列リテラル内の文字は、プログラムの実行時にデータとして扱われます。

ルーンリテラル (Rune literals)

Go言語におけるルーンリテラルは、単一のUnicodeコードポイントを表す文字定数です。シングルクォート (') で囲まれて表現されます。例: 'A', '世'。Goでは、rune 型はUTF-8でエンコードされた文字ではなく、Unicodeコードポイント(int32のエイリアス)を表します。ルーンリテラル内の文字も、プログラムの実行時にデータとして扱われます。

技術的詳細

このコミットによってGo言語の仕様に追加された「実装上の制約」は、Goコンパイラがソースコードを解析する際のBOMの扱いを明確にします。

変更前は、Goコンパイラがソースファイルの先頭にBOMを見つけた場合、それをどのように扱うか(エラーとするか、無視するか、あるいは通常の文字として解釈するか)は明確に定義されていませんでした。これにより、BOMが付加されたファイルがコンパイルエラーになったり、予期せぬ動作を引き起こしたりする可能性がありました。

変更後は、Goコンパイラは以下のルールに従うことが許可されます。

  1. 文字列リテラルおよびルーンリテラルの外部: ソースコードの通常の実行可能コード部分やコメント、識別子などの領域にBOM (U+FEFF) が存在する場合、コンパイラはこれを無視してもよいとされます。これは、BOMがコードのセマンティクスに影響を与えないようにするための措置です。これにより、BOMが付加されたファイルでも、コンパイルエラーなしに処理できるようになります。
  2. 文字列リテラルおよびルーンリテラルの内部: 文字列リテラルやルーンリテラルの中にBOMが存在する場合、コンパイラはそれを無視してはならないと解釈されます。これは、BOMがこれらのリテラルの一部として意図的に含まれている可能性があるためです。例えば、"Hello\uFEFFWorld" のような文字列は、BOMを通常の文字として含んでいると解釈されるべきです。

この変更は、Goコンパイラの実装に柔軟性を持たせ、特にWindows環境で作成されたソースファイルとの互換性を高めることを目的としています。これにより、開発者は異なるOSやエディタで作成されたGoソースファイルをよりシームレスに扱えるようになります。

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

変更は doc/go_spec.html ファイルに対して行われました。これはGo言語の公式仕様書であり、言語の動作を定義する重要なドキュメントです。

--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
 <!--{
  	"Title": "The Go Programming Language Specification",
-	"Subtitle": "Version of September 4, 2012",
+	"Subtitle": "Version of September 6, 2012",
  	"Path": "/ref/spec"
 }-->
 
@@ -99,6 +99,12 @@ are different characters.
 Implementation restriction: For compatibility with other tools, a
 compiler may disallow the NUL character (U+0000) in the source text.
 </p>
+<p>
+Implementation restriction: For compatibility with other tools, a
+compiler may ignore any UTF-8-encoded Unicode byte order mark
+(U+FEFF) in the source text outside of <a href="#String_literals">string</a>
+and <a href="#Rune_literals">rune</a> literals.
+</p>
 
 <h3 id="Characters">Characters</h3>
 

コアとなるコードの解説

このコミットは、Go言語の仕様書に以下の新しい段落を追加しています。

<p>
Implementation restriction: For compatibility with other tools, a
compiler may ignore any UTF-8-encoded Unicode byte order mark
(U+FEFF) in the source text outside of <a href="#String_literals">string</a>
and <a href="#Rune_literals">rune</a> literals.
</p>

この追加により、Go言語の仕様に「実装上の制約」として、コンパイラがUTF-8エンコードされたBOM (U+FEFF) を、文字列リテラルおよびルーンリテラルの外部にあるソーステキスト中で無視してもよい、という規定が明記されました。

  • Implementation restriction:: これは、言語のコアな動作ではなく、コンパイラの実装が従うべき推奨事項または許容される動作であることを示します。
  • For compatibility with other tools,: この制約が、他の開発ツール(テキストエディタ、IDEなど)との連携や互換性を目的としていることを明確にしています。
  • a compiler may ignore any UTF-8-encoded Unicode byte order mark (U+FEFF) in the source text: コンパイラがソースコード中のUTF-8 BOM (U+FEFF) を無視することを許可します。
  • outside of <a href="#String_literals">string</a> and <a href="#Rune_literals">rune</a> literals.: BOMを無視する対象が、文字列リテラルとルーンリテラルの外部に限定されることを示します。これにより、リテラル内に意図的に含まれたBOMが誤って無視されることを防ぎます。

この変更は、Go言語のコンパイラがBOMを含むソースファイルをより寛容に扱えるようにするための、仕様レベルでの重要な更新です。

関連リンク

参考にした情報源リンク