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

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

このコミットは、Go言語の実験的なパッケージである exp/norm におけるUnicodeバージョンの取り扱いに関する変更です。具体的には、Unicodeデータベース(UCD)のURLにハードコードされていたUnicodeバージョン文字列を、Goの標準ライブラリ unicode パッケージが提供する unicode.Version 定数に置き換えることで、パッケージ間のUnicodeバージョンの一貫性を確保することを目的としています。

コミット

commit 18aded7ab924d32be1dcd4b82c904947fd537434
Author: Marcel van Lohuizen <mpvl@golang.org>
Date:   Mon May 7 11:41:40 2012 +0200

    exp/norm: It is important that the unicode versions of the various packages align.
    Replace hard-coded version strings with unicode.Version.
    
    R=r, r
    CC=golang-dev
    https://golang.org/cl/6163045

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

https://github.com/golang/go/commit/18aded7ab924d32be1dcd4b82c904947fd537434

元コミット内容

exp/norm: さまざまなパッケージのUnicodeバージョンが一致していることが重要です。 ハードコードされたバージョン文字列を unicode.Version に置き換えます。

変更の背景

このコミットの背景には、Go言語のUnicode関連パッケージ、特に正規化(Normalization)を扱う exp/norm パッケージが、Goランタイム自体がサポートするUnicodeバージョンと常に同期している必要があるという重要な要件があります。

以前のコードでは、Unicodeデータベース(UCD: Unicode Character Database)の特定のバージョン(例: 6.0.0)へのURLがハードコードされていました。UCDは、Unicode文字のプロパティ、正規化データ、スクリプト情報など、Unicodeの動作を定義するデータファイル群です。Goの unicode パッケージは、これらのUCDデータに基づいて実装されており、特定のUnicodeバージョンに準拠しています。

もし exp/norm パッケージが古い、あるいはGoランタイムがサポートするバージョンと異なるUCDバージョンを参照し続けると、以下のような問題が発生する可能性があります。

  1. 不整合な動作: Unicode正規化のルールはUnicodeのバージョンアップに伴い変更されることがあります。exp/norm が古いルールに基づいて動作すると、Goランタイムの他の部分や、Goで書かれた他のアプリケーションが期待する正規化結果と異なる結果を生成し、互換性の問題やバグを引き起こす可能性があります。
  2. メンテナンスの複雑化: Unicodeの新しいバージョンがリリースされるたびに、ハードコードされたバージョン文字列を手動で更新する必要があり、これはエラーの温床となり、メンテナンスコストを増加させます。
  3. セキュリティリスク: 古いUCDデータを使用し続けると、既知のUnicode関連の脆弱性(例: 特定の正規化形式の悪用)が修正されないままになる可能性があります。

このコミットは、これらの問題を解決し、Goエコシステム全体でUnicodeの取り扱いの一貫性と正確性を保証するために行われました。unicode.Version を使用することで、Goのビルド時にGoランタイムがサポートするUnicodeバージョンが自動的に反映されるようになり、手動での同期作業が不要になります。

前提知識の解説

Unicode

Unicodeは、世界中のあらゆる文字をコンピュータで扱えるようにするための文字コードの国際標準です。異なる言語の文字を単一の文字セットで表現することを目的としており、絵文字や特殊記号なども含まれます。各文字には一意のコードポイントが割り当てられています。

Unicode正規化 (Unicode Normalization)

Unicodeには、同じ文字でも複数の表現形式が存在する場合があります。例えば、アクセント付きの文字は、単一のコードポイントで表現される「合成済み文字(Precomposed Character)」と、基本文字とアクセント記号が別々のコードポイントで表現される「結合文字シーケンス(Combining Character Sequence)」の2通りの方法で表現できます。

例:

  • é (U+00E9, LATIN SMALL LETTER E WITH ACUTE)
  • e (U+0065, LATIN SMALL LETTER E) + ´ (U+0301, COMBINING ACUTE ACCENT)

これらは視覚的には同じに見えますが、バイナリレベルでは異なるシーケンスです。この違いは、文字列の比較、検索、ソートなどの操作において問題を引き起こす可能性があります。

Unicode正規化は、このような複数の表現形式を持つ文字シーケンスを、特定の「正規化形式」に変換するプロセスです。これにより、異なる表現形式の文字列でも、正規化後に同じバイナリ表現になるため、正確な比較や処理が可能になります。

主な正規化形式には以下の4つがあります。

  • NFC (Normalization Form Canonical Composition): 互換等価な文字を合成済み文字に変換します。最も一般的に使用される形式です。
  • NFD (Normalization Form Canonical Decomposition): 互換等価な文字を結合文字シーケンスに分解します。
  • NFKC (Normalization Form Compatibility Composition): 互換等価と互換性等価の両方を考慮し、合成済み文字に変換します。
  • NFKD (Normalization Form Compatibility Decomposition): 互換等価と互換性等価の両方を考慮し、結合文字シーケンスに分解します。

exp/norm パッケージは、これらのUnicode正規化の機能を提供する実験的なパッケージです。

Unicode Character Database (UCD)

Unicode Character Database (UCD) は、Unicode標準の一部としてUnicode Consortiumによって提供されるデータファイルの集合体です。これらのファイルには、各Unicodeコードポイントに関する膨大な情報が含まれています。例えば、文字のカテゴリ、スクリプト、双方向性プロパティ、大文字・小文字変換ルール、そして正規化に必要な分解・合成マッピングなどが定義されています。

UCDは、Unicodeのバージョンアップごとに更新され、新しい文字の追加や既存の文字プロパティの修正が行われます。Go言語の unicode パッケージや、他のプログラミング言語のUnicodeライブラリは、これらのUCDデータに基づいて実装されています。

Go言語の unicode パッケージと unicode.Version

Go言語の標準ライブラリには、Unicode文字のプロパティ、文字クラス、大文字・小文字変換、正規化などの機能を提供する unicode パッケージが含まれています。このパッケージは、Goのリリースごとに特定のUnicodeバージョンに準拠するように更新されます。

unicode.Version は、unicode パッケージが現在サポートしているUnicodeのバージョンを表す文字列定数です。例えば、Go 1.18ではUnicode 13.0.0をサポートしており、unicode.Version は "13.0.0" となります。この定数を使用することで、Goプログラムは実行されているGoランタイムがサポートするUnicodeバージョンを動的に参照できます。

Go言語の exp パッケージ

Go言語の標準ライブラリには、exp というプレフィックスを持つパッケージ群が存在します。これらは「実験的(experimental)」なパッケージであり、まだ安定版の標準ライブラリには含まれていません。exp パッケージは、将来的に標準ライブラリに組み込まれる可能性のある新機能やAPIを先行して提供し、コミュニティからのフィードバックを募るために使用されます。

exp/norm もその一つであり、Unicode正規化の機能を提供しています。実験的な性質上、APIが変更されたり、最終的に標準ライブラリに組み込まれない可能性もあります。

技術的詳細

このコミットの技術的な核心は、Goのビルドシステムと unicode パッケージの連携を利用して、UnicodeデータベースのURLを動的に構築することにあります。

変更前は、src/pkg/exp/norm/maketables.gosrc/pkg/exp/norm/normregtest.go の両ファイルで、UnicodeデータベースのURLが以下のようにハードコードされていました。

"http://www.unicode.org/Public/6.0.0/ucd/"

そして、normregtest.go のコメントにも同様のバージョンが記載されていました。

// (taken from http://www.unicode.org/Public/6.0.0/ucd/).

この 6.0.0 という部分は、Unicodeの特定のバージョンを指しています。Goの unicode パッケージは、Goのリリースサイクルに合わせて、特定のUnicodeバージョンに準拠するように更新されます。例えば、Go 1.0がUnicode 6.0.0をサポートしていたとしても、将来のGoのバージョンではUnicode 6.1.0、7.0.0など、より新しいバージョンをサポートするようになる可能性があります。

このコミットでは、このハードコードされたバージョン文字列を unicode.Version に置き換えることで、GoランタイムがサポートするUnicodeバージョンと exp/norm パッケージが参照するUCDのバージョンを自動的に同期させます。

具体的には、以下の変更が行われました。

  1. unicode パッケージのインポート: src/pkg/exp/norm/maketables.gosrc/pkg/exp/norm/normregtest.go の両方に import "unicode" が追加されました。これにより、unicode パッケージが提供する定数や関数を利用できるようになります。

  2. URL文字列の動的生成: ハードコードされた 6.0.0 の部分が unicode.Version に置き換えられました。

    変更前:

    "http://www.unicode.org/Public/6.0.0/ucd/"
    

    変更後:

    "http://www.unicode.org/Public/"+unicode.Version+"/ucd/"
    

    これにより、Goプログラムがコンパイルされる際に、そのGoバージョンがサポートする unicode.Version の値が文字列に埋め込まれ、常に最新かつ適切なUCDのURLが参照されるようになります。

  3. コメントの更新: normregtest.go のコメントも同様に更新され、動的なバージョン参照が示唆されるようになりました。

    変更前:

    // (taken from http://www.unicode.org/Public/6.0.0/ucd/).
    

    変更後:

    // (taken from http://www.unicode.org/Public/<unicode.Version>/ucd/).
    

この変更により、exp/norm パッケージは、GoランタイムのUnicodeサポートと常に整合性の取れたUCDデータを使用するようになり、将来のUnicodeバージョンアップにも自動的に対応できるようになります。これは、Go言語のUnicode処理の堅牢性とメンテナンス性を向上させる上で非常に重要な改善です。

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

src/pkg/exp/norm/maketables.go

--- a/src/pkg/exp/norm/maketables.go
+++ b/src/pkg/exp/norm/maketables.go
@@ -23,6 +23,7 @@ import (
 	"sort"
 	"strconv"
 	"strings"
+	"unicode" // 追加
 )
 
 func main() {
@@ -38,7 +39,7 @@ func main() {
 }
 
 var url = flag.String("url",
-	"http://www.unicode.org/Public/6.0.0/ucd/", // 変更前
+	"http://www.unicode.org/Public/"+unicode.Version+"/ucd/", // 変更後
 	"URL of Unicode database directory")
 var tablelist = flag.String("tables",
 	"all",

src/pkg/exp/norm/normregtest.go

--- a/src/pkg/exp/norm/normregtest.go
+++ b/src/pkg/exp/norm/normregtest.go
@@ -22,6 +22,7 @@ import (
 	"strconv"
 	"strings"
 	"time"
+	"unicode" // 追加
 	"unicode/utf8"
 )
 
@@ -39,7 +40,7 @@ func main() {
 const file = "NormalizationTest.txt"
 
 var url = flag.String("url",
-	"http://www.unicode.org/Public/6.0.0/ucd/"+file, // 変更前
+	"http://www.unicode.org/Public/"+unicode.Version+"/ucd/"+file, // 変更後
 	"URL of Unicode database directory")
 var localFiles = flag.Bool("local",
 	false,
@@ -48,7 +49,7 @@ var localFiles = flag.Bool("local",
 var logger = log.New(os.Stderr, "", log.Lshortfile)
 
 // This regression test runs the test set in NormalizationTest.txt
-// (taken from http://www.unicode.org/Public/6.0.0/ucd/). // 変更前
+// (taken from http://www.unicode.org/Public/<unicode.Version>/ucd/). // 変更後
 //
 // NormalizationTest.txt has form:
 // @Part0 # Specific cases

コアとなるコードの解説

このコミットのコアとなる変更は、unicode パッケージのインポートと、flag.String で定義されているURL文字列の変更です。

  1. import "unicode" の追加: これは、unicode パッケージが提供する Version 定数を使用するために必須のステップです。Goでは、使用するパッケージは明示的にインポートする必要があります。

  2. flag.String のURL定義の変更: flag.String は、コマンドライン引数から文字列値を受け取るためのGoの標準ライブラリ flag パッケージの関数です。ここでは、UnicodeデータベースのURLを定義する url フラグのデフォルト値が変更されています。

    変更前は、URLが "http://www.unicode.org/Public/6.0.0/ucd/" のように、Unicodeバージョン 6.0.0 が直接埋め込まれていました。 変更後は、これが "http://www.unicode.org/Public/"+unicode.Version+"/ucd/" となっています。

    この変更により、Goコンパイラは unicode.Version の実際の値(例えば、Go 1.0がサポートするUnicode 6.0.0であれば "6.0.0")を文字列に展開します。結果として、生成されるURLはGoランタイムがサポートするUnicodeバージョンに常に一致するようになります。

    同様の変更が normregtest.gourl フラグと、その下のコメントにも適用されています。normregtest.go は正規化の回帰テストを行うためのファイルであり、テストデータもUCDから取得するため、ここでもバージョンの一貫性が重要です。コメントの変更は、コードの意図を明確にし、将来の読者がこの動的なバージョン参照を理解しやすくするためのものです。

このシンプルな変更により、exp/norm パッケージはGoランタイムのUnicodeサポートと密接に連携し、将来のUnicodeバージョンアップにも自動的に追従できるようになり、Go言語のUnicode処理の信頼性と保守性が大幅に向上しました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Unicode Consortiumの公式ウェブサイト
  • Gitコミットログと差分
  • Go言語のソースコードリポジトリ
  • Wikipedia: Unicode正規化
  • Stack Overflowなどの技術Q&Aサイト (一般的なGoのパッケージインポートや文字列結合の知識)
  • Go言語の flag パッケージのドキュメント: https://pkg.go.dev/flag
  • Go言語の exp パッケージに関する情報 (Goのリリースノートやブログ記事など)
  • Go CL 6163045: https://golang.org/cl/6163045 (コミットメッセージに記載されているChange Listへのリンク)