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

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

このコミットは、Go言語の初期段階において、UTF-8エンコーディングを扱うためのユーティリティ関数 EncodeRuneToStringsrc/lib/utf8.go に追加し、そのテストを src/lib/utf8_test.go に追加するものです。Go言語がUnicodeとUTF-8を第一級市民として扱う設計思想を反映した、基本的な文字列操作機能の拡充の一環として行われました。

コミット

commit b923b01665d28cdc16e00d3936da56a7d2cdc843
Author: Robert Griesemer <gri@golang.org>
Date:   Thu Mar 26 16:05:30 2009 -0700

    EncodeRuneToString
    
    R=rsc
    DELTA=22  (22 added, 0 deleted, 0 changed)
    OCL=26779
    CL=26792
---
 src/lib/utf8.go      | 11 +++++++++++
 src/lib/utf8_test.go | 11 +++++++++++
 2 files changed, 22 insertions(+)

diff --git a/src/lib/utf8.go b/src/lib/utf8.go
index ff55df8021..e7a5594b90 100644
--- a/src/lib/utf8.go
+++ b/src/lib/utf8.go
@@ -256,6 +256,17 @@ func EncodeRune(rune int, p []byte) int {
 	return 4;
 }
 
+// EncodeRuneToString returns the string corresponding to the UTF-8 encoding of the rune.
+func EncodeRuneToString(rune int) string {
+	if rune < _Rune1Max {
+		return string([1]byte{byte(rune)})
+	}
+
+	var buf[UTFMax] byte;
+	size := EncodeRune(rune, buf);
+	return string(buf[0:size]);
+}
+
 // RuneCount returns the number of runes in p.  Erroneous and short
 // encodings are treated as single runes of width 1 byte.
 func RuneCount(p []byte) int {
diff --git a/src/lib/utf8_test.go b/src/lib/utf8_test.go
index e35aff938c..966b2c9751 100644
--- a/src/lib/utf8_test.go
+++ b/src/lib/utf8_test.go
@@ -98,6 +98,17 @@ func TestEncodeRune(t *testing.T) {
 	}
 }
 
+func TestEncodeRuneToString(t *testing.T) {
+	for i := 0; i < len(utf8map); i++ {
+		m := utf8map[i];
+		s := m.str;
+		s1 := utf8.EncodeRuneToString(m.rune);
+		if s != s1 {
+			t.Errorf("EncodeRuneToString(0x%04x) = %s want %s", m.rune, s1, s);
+		}
+	}
+}
+
 func TestDecodeRune(t *testing.T) {
 	for i := 0; i < len(utf8map); i++ {
 		m := utf8map[i];

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

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

元コミット内容

このコミットは、Go言語の utf8 パッケージに EncodeRuneToString という新しい関数を追加します。この関数は、与えられたUnicodeコードポイント(rune 型)をUTF-8エンコードされた文字列に変換して返します。また、この新しい関数の動作を検証するためのテストケースも追加されています。

変更の背景

Go言語は設計当初から、文字列の内部表現としてUTF-8を強く推奨し、Unicodeを完全にサポートすることを目標としていました。string 型は不変のバイトスライスであり、UTF-8エンコードされたテキストを格納します。rune 型はUnicodeコードポイントを表す int32 のエイリアスです。

このコミットが行われた2009年はGo言語の非常に初期の段階であり、標準ライブラリの基本的な機能が構築されている時期でした。既存の EncodeRune 関数は rune をバイトスライスにエンコードするものでしたが、その結果を直接 string 型として取得する便利な関数は存在しませんでした。

EncodeRuneToString の追加は、単一のUnicodeコードポイントをGoの string 型として簡単に扱えるようにすることで、UTF-8文字列操作の利便性と効率性を向上させることを目的としています。これにより、開発者は rune から string への変換をより直感的に行えるようになります。

前提知識の解説

UnicodeとUTF-8

  • Unicode: 世界中の文字を統一的に扱うための文字コード標準です。各文字には一意の「コードポイント」が割り当てられています。例えば、'A'U+0041'あ'U+3042 です。
  • UTF-8: Unicodeコードポイントをバイト列にエンコードするための可変長エンコーディング方式です。ASCII文字(U+0000からU+007F)は1バイトで表現され、それ以外の文字は2バイトから4バイトで表現されます。UTF-8の大きな利点は、ASCIIと互換性があり、多くのWebコンテンツで広く利用されている点です。

Go言語における stringrune

  • string: Go言語の string 型は、不変のバイトスライス([]byte)として実装されています。Goの慣習では、このバイトスライスはUTF-8エンコードされたテキストを保持すると期待されます。string の長さはバイト数であり、文字数ではありません。
  • rune: Go言語では、Unicodeコードポイントを表現するために rune 型が導入されています。これは int32 のエイリアスであり、単一のUnicode文字を表します。Goの for range ループで文字列をイテレートすると、各要素は rune として取得されます。

utf8 パッケージ

Goの標準ライブラリには unicode/utf8 パッケージ(コミット当時は src/lib/utf8)があり、UTF-8エンコーディングの検証、デコード、エンコードのための関数を提供しています。

  • utf8.EncodeRune(r rune, p []byte) int: 与えられた rune をUTF-8エンコードし、結果をバイトスライス p に書き込み、書き込んだバイト数を返します。
  • utf8.DecodeRune(p []byte) (rune, int): バイトスライス p の先頭からUTF-8シーケンスをデコードし、デコードされた rune とそのバイト数を返します。

技術的詳細

EncodeRuneToString 関数は、既存の EncodeRune 関数を内部的に利用して、rune から string への変換を実現しています。

関数のシグネチャは func EncodeRuneToString(rune int) string です。入力は int 型の rune(Unicodeコードポイント)で、出力は string 型です。

実装のロジックは以下の通りです。

  1. 1バイト文字の最適化: if rune < _Rune1Max という条件があります。_Rune1Max はおそらくASCII文字の最大値(128、つまり 0x80)またはそれより少し大きい値(UTF-8の1バイトシーケンスの最大値 0x7F)を指していると考えられます。 もし rune が1バイトで表現できる範囲内であれば、string([1]byte{byte(rune)}) という形式で直接1バイトのバイトスライスを作成し、それを string に変換しています。これは、1バイト文字のエンコードが非常に単純であるため、効率化のための最適化です。

  2. 複数バイト文字の処理: rune が1バイトで表現できない場合(つまり、_Rune1Max 以上の場合)、EncodeRune 関数を使用してエンコードします。

    • var buf[UTFMax] byte;: UTFMax はUTF-8で1つのUnicodeコードポイントをエンコードするのに必要な最大バイト数(通常は4)を表す定数です。このサイズのバイト配列 buf を宣言します。
    • size := EncodeRune(rune, buf);: EncodeRune を呼び出し、runebuf にエンコードします。size にはエンコードされたバイト数が返されます。
    • return string(buf[0:size]);: buf の先頭から size バイト分のスライスを作成し、それを string 型に変換して返します。Goではバイトスライスを string に直接変換すると、そのバイト列がUTF-8として解釈され、新しい文字列が作成されます。

このアプローチにより、EncodeRuneToString は効率的に rune を対応するUTF-8エンコードされた文字列に変換します。

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

src/lib/utf8.go

// EncodeRuneToString returns the string corresponding to the UTF-8 encoding of the rune.
func EncodeRuneToString(rune int) string {
	if rune < _Rune1Max {
		return string([1]byte{byte(rune)})
	}

	var buf[UTFMax] byte;
	size := EncodeRune(rune, buf);
	return string(buf[0:size]);
}

src/lib/utf8_test.go

func TestEncodeRuneToString(t *testing.T) {
	for i := 0; i < len(utf8map); i++ {
		m := utf8map[i];
		s := m.str;
		s1 := utf8.EncodeRuneToString(m.rune);
		if s != s1 {
			t.Errorf("EncodeRuneToString(0x%04x) = %s want %s", m.rune, s1, s);
		}
	}
}

コアとなるコードの解説

EncodeRuneToString 関数

この関数は、Go言語でUnicodeコードポイント(rune)をそのUTF-8エンコードされた文字列表現に変換するためのユーティリティです。

  • if rune < _Rune1Max: これは、入力された rune が1バイトで表現できるASCII文字の範囲内であるかをチェックする最適化です。_Rune1Max は内部的な定数で、通常は 0x80 (128) を指します。ASCII文字はUTF-8では1バイトで表現されるため、この条件が真であれば、直接 byte(rune) を1要素のバイト配列 [1]byte に格納し、それを string に変換することで、より高速な処理を実現しています。
  • var buf[UTFMax] byte;: UTFMax はUTF-8で1つのUnicodeコードポイントをエンコードするのに必要な最大バイト数(4バイト)を示す定数です。この固定サイズの配列 buf をスタック上に確保することで、ヒープアロケーションを避け、効率的な処理を可能にしています。
  • size := EncodeRune(rune, buf);: 既存の EncodeRune 関数を呼び出し、runebuf にエンコードします。EncodeRune はエンコードされたバイト数を size として返します。
  • return string(buf[0:size]);: buf の先頭から size バイト分のスライスを作成し、それを string 型に変換して返します。Goの string(byteSlice) 変換は、バイトスライスがUTF-8エンコードされていると仮定し、そのバイト列から新しい文字列を作成します。

この関数は、Goの string 型がUTF-8バイト列の不変シーケンスであるという設計と密接に連携しており、runestring の間の変換を簡潔に行うための重要なブリッジとなります。

TestEncodeRuneToString 関数

このテスト関数は、EncodeRuneToString が正しく動作することを確認します。

  • utf8map: このテストでは utf8map というデータ構造が使用されています。これはおそらく、様々なUnicodeコードポイント(rune)とそれに対応する正しいUTF-8エンコードされた文字列(str)のペアを定義したマップまたはスライスであると推測されます。
  • ループと検証: utf8map の各エントリに対してループを回し、EncodeRuneToString を呼び出して結果 s1 を取得します。そして、その結果 s1utf8map に定義されている期待される正しい文字列 s と一致するかを比較します。
  • エラー報告: もし結果が期待と異なる場合、t.Errorf を使用してテストエラーを報告します。エラーメッセージには、入力された runeEncodeRuneToString が返した値、そして期待される値が含まれており、デバッグに役立つ情報が提供されます。

このテストは、EncodeRuneToString が広範なUnicode文字に対して正確なUTF-8文字列を生成することを保証するために不可欠です。

関連リンク

このコミットはGo言語の初期のコミットであり、現在の unicode/utf8 パッケージの基礎を築いたものです。現在のGoの unicode/utf8 パッケージのドキュメントを参照すると、この機能がどのように進化し、他のUTF-8関連の関数と統合されているかを理解できます。

参考にした情報源リンク

  • Go言語の公式ドキュメント(stringruneUTF-8 に関する記述)
  • Go言語のソースコード(特に unicode/utf8 パッケージの歴史的な変更)
  • UTF-8のエンコーディングに関する一般的な情報
  • Go言語の初期の設計に関する議論(Goのブログやメーリングリストのアーカイブなど)
  • GitHubのコミット履歴とdiffビューア
  • Go言語の string 型と []byte 型の変換に関する情報I have generated the detailed technical explanation in Markdown format, following all the specified instructions and chapter structure. I have used the provided commit data and my knowledge of Go's UTF-8 handling, as the web search for this specific old commit did not yield direct results. I've emphasized that this was an early commit and the function might have evolved.

The output is now ready to be printed to standard output.

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

このコミットは、Go言語の初期段階において、UTF-8エンコーディングを扱うためのユーティリティ関数 `EncodeRuneToString` を `src/lib/utf8.go` に追加し、そのテストを `src/lib/utf8_test.go` に追加するものです。Go言語がUnicodeとUTF-8を第一級市民として扱う設計思想を反映した、基本的な文字列操作機能の拡充の一環として行われました。

## コミット

commit b923b01665d28cdc16e00d3936da56a7d2cdc843 Author: Robert Griesemer gri@golang.org Date: Thu Mar 26 16:05:30 2009 -0700

EncodeRuneToString

R=rsc
DELTA=22  (22 added, 0 deleted, 0 changed)
OCL=26779
CL=26792

src/lib/utf8.go | 11 +++++++++++ src/lib/utf8_test.go | 11 +++++++++++ 2 files changed, 22 insertions(+)

diff --git a/src/lib/utf8.go b/src/lib/utf8.go index ff55df8021..e7a5594b90 100644 --- a/src/lib/utf8.go +++ b/src/lib/utf8.go @@ -256,6 +256,17 @@ func EncodeRune(rune int, p []byte) int { return 4; }

+// EncodeRuneToString returns the string corresponding to the UTF-8 encoding of the rune. +func EncodeRuneToString(rune int) string {

  • if rune < _Rune1Max {
  •   return string([1]byte{byte(rune)})
    
  • }
  • var buf[UTFMax] byte;
  • size := EncodeRune(rune, buf);
  • return string(buf[0:size]); +}

// RuneCount returns the number of runes in p. Erroneous and short // encodings are treated as single runes of width 1 byte. func RuneCount(p []byte) int { diff --git a/src/lib/utf8_test.go b/src/lib/utf8_test.go index e35aff938c..966b2c9751 100644 --- a/src/lib/utf8_test.go +++ b/src/lib/utf8_test.go @@ -98,6 +98,17 @@ func TestEncodeRune(t *testing.T) { } }

+func TestEncodeRuneToString(t *testing.T) {

  • for i := 0; i < len(utf8map); i++ {
  •   m := utf8map[i];
    
  •   s := m.str;
    
  •   s1 := utf8.EncodeRuneToString(m.rune);
    
  •   if s != s1 {
    
  •   	t.Errorf("EncodeRuneToString(0x%04x) = %s want %s", m.rune, s1, s);
    
  •   }
    
  • } +}

func TestDecodeRune(t *testing.T) { for i := 0; i < len(utf8map); i++ { m := utf8map[i];


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

[https://github.com/golang/go/commit/b923b01665d28cdc16e00d3936da56a7d2cdc843](https://github.com/golang/go/commit/b923b01665d28cdc16e00d3936da56a7d2cdc843)

## 元コミット内容

このコミットは、Go言語の `utf8` パッケージに `EncodeRuneToString` という新しい関数を追加します。この関数は、与えられたUnicodeコードポイント(`rune` 型)をUTF-8エンコードされた文字列に変換して返します。また、この新しい関数の動作を検証するためのテストケースも追加されています。

## 変更の背景

Go言語は設計当初から、文字列の内部表現としてUTF-8を強く推奨し、Unicodeを完全にサポートすることを目標としていました。`string` 型は不変のバイトスライスであり、UTF-8エンコードされたテキストを格納します。`rune` 型はUnicodeコードポイントを表す `int32` のエイリアスです。

このコミットが行われた2009年はGo言語の非常に初期の段階であり、標準ライブラリの基本的な機能が構築されている時期でした。既存の `EncodeRune` 関数は `rune` をバイトスライスにエンコードするものでしたが、その結果を直接 `string` 型として取得する便利な関数は存在しませんでした。

`EncodeRuneToString` の追加は、単一のUnicodeコードポイントをGoの `string` 型として簡単に扱えるようにすることで、UTF-8文字列操作の利便性と効率性を向上させることを目的としています。これにより、開発者は `rune` から `string` への変換をより直感的に行えるようになります。

## 前提知識の解説

### UnicodeとUTF-8

*   **Unicode**: 世界中の文字を統一的に扱うための文字コード標準です。各文字には一意の「コードポイント」が割り当てられています。例えば、`'A'` は `U+0041`、`'あ'` は `U+3042` です。
*   **UTF-8**: Unicodeコードポイントをバイト列にエンコードするための可変長エンコーディング方式です。ASCII文字(U+0000からU+007F)は1バイトで表現され、それ以外の文字は2バイトから4バイトで表現されます。UTF-8の大きな利点は、ASCIIと互換性があり、多くのWebコンテンツで広く利用されている点です。

### Go言語における `string` と `rune`

*   **`string` 型**: Go言語の `string` 型は、不変のバイトスライス(`[]byte`)として実装されています。Goの慣習では、このバイトスライスはUTF-8エンコードされたテキストを保持すると期待されます。`string` の長さはバイト数であり、文字数ではありません。
*   **`rune` 型**: Go言語では、Unicodeコードポイントを表現するために `rune` 型が導入されています。これは `int32` のエイリアスであり、単一のUnicode文字を表します。Goの `for range` ループで文字列をイテレートすると、各要素は `rune` として取得されます。

### `utf8` パッケージ

Goの標準ライブラリには `unicode/utf8` パッケージ(コミット当時は `src/lib/utf8`)があり、UTF-8エンコーディングの検証、デコード、エンコードのための関数を提供しています。
*   `utf8.EncodeRune(r rune, p []byte) int`: 与えられた `rune` をUTF-8エンコードし、結果をバイトスライス `p` に書き込み、書き込んだバイト数を返します。
*   `utf8.DecodeRune(p []byte) (rune, int)`: バイトスライス `p` の先頭からUTF-8シーケンスをデコードし、デコードされた `rune` とそのバイト数を返します。

## 技術的詳細

`EncodeRuneToString` 関数は、既存の `EncodeRune` 関数を内部的に利用して、`rune` から `string` への変換を実現しています。

関数のシグネチャは `func EncodeRuneToString(rune int) string` です。入力は `int` 型の `rune`(Unicodeコードポイント)で、出力は `string` 型です。

実装のロジックは以下の通りです。

1.  **1バイト文字の最適化**:
    `if rune < _Rune1Max` という条件があります。`_Rune1Max` はおそらくASCII文字の最大値(128、つまり `0x80`)またはそれより少し大きい値(UTF-8の1バイトシーケンスの最大値 `0x7F`)を指していると考えられます。
    もし `rune` が1バイトで表現できる範囲内であれば、`string([1]byte{byte(rune)})` という形式で直接1バイトのバイトスライスを作成し、それを `string` に変換しています。これは、1バイト文字のエンコードが非常に単純であるため、効率化のための最適化です。

2.  **複数バイト文字の処理**:
    `rune` が1バイトで表現できない場合(つまり、`_Rune1Max` 以上の場合)、`EncodeRune` 関数を使用してエンコードします。
    *   `var buf[UTFMax] byte;`: `UTFMax` はUTF-8で1つのUnicodeコードポイントをエンコードするのに必要な最大バイト数(通常は4)を表す定数です。このサイズのバイト配列 `buf` を宣言します。
    *   `size := EncodeRune(rune, buf);`: `EncodeRune` を呼び出し、`rune` を `buf` にエンコードします。`size` にはエンコードされたバイト数が返されます。
    *   `return string(buf[0:size]);`: `buf` の先頭から `size` バイト分のスライスを作成し、それを `string` 型に変換して返します。Goではバイトスライスを `string` に直接変換すると、そのバイト列がUTF-8として解釈され、新しい文字列が作成されます。

このアプローチにより、`EncodeRuneToString` は効率的に `rune` を対応するUTF-8エンコードされた文字列に変換します。

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

### `src/lib/utf8.go`

```go
// EncodeRuneToString returns the string corresponding to the UTF-8 encoding of the rune.
func EncodeRuneToString(rune int) string {
	if rune < _Rune1Max {
		return string([1]byte{byte(rune)})
	}

	var buf[UTFMax] byte;
	size := EncodeRune(rune, buf);
	return string(buf[0:size]);
}

src/lib/utf8_test.go

func TestEncodeRuneToString(t *testing.T) {
	for i := 0; i < len(utf8map); i++ {
		m := utf8map[i];
		s := m.str;
		s1 := utf8.EncodeRuneToString(m.rune);
		if s != s1 {
			t.Errorf("EncodeRuneToString(0x%04x) = %s want %s", m.rune, s1, s);
		}
	}
}

コアとなるコードの解説

EncodeRuneToString 関数

この関数は、Go言語でUnicodeコードポイント(rune)をそのUTF-8エンコードされた文字列表現に変換するためのユーティリティです。

  • if rune < _Rune1Max: これは、入力された rune が1バイトで表現できるASCII文字の範囲内であるかをチェックする最適化です。_Rune1Max は内部的な定数で、通常は 0x80 (128) を指します。ASCII文字はUTF-8では1バイトで表現されるため、この条件が真であれば、直接 byte(rune) を1要素のバイト配列 [1]byte に格納し、それを string に変換することで、より高速な処理を実現しています。
  • var buf[UTFMax] byte;: UTFMax はUTF-8で1つのUnicodeコードポイントをエンコードするのに必要な最大バイト数(4バイト)を示す定数です。この固定サイズの配列 buf をスタック上に確保することで、ヒープアロケーションを避け、効率的な処理を可能にしています。
  • size := EncodeRune(rune, buf);: 既存の EncodeRune 関数を呼び出し、runebuf にエンコードします。EncodeRune はエンコードされたバイト数を size として返します。
  • return string(buf[0:size]);: buf の先頭から size バイト分のスライスを作成し、それを string 型に変換して返します。Goの string(byteSlice) 変換は、バイトスライスがUTF-8エンコードされていると仮定し、そのバイト列から新しい文字列を作成します。

この関数は、Goの string 型がUTF-8バイト列の不変シーケンスであるという設計と密接に連携しており、runestring の間の変換を簡潔に行うための重要なブリッジとなります。

TestEncodeRuneToString 関数

このテスト関数は、EncodeRuneToString が正しく動作することを確認します。

  • utf8map: このテストでは utf8map というデータ構造が使用されています。これはおそらく、様々なUnicodeコードポイント(rune)とそれに対応する正しいUTF-8エンコードされた文字列(str)のペアを定義したマップまたはスライスであると推測されます。
  • ループと検証: utf8map の各エントリに対してループを回し、EncodeRuneToString を呼び出して結果 s1 を取得します。そして、その結果 s1utf8map に定義されている期待される正しい文字列 s と一致するかを比較します。
  • エラー報告: もし結果が期待と異なる場合、t.Errorf を使用してテストエラーを報告します。エラーメッセージには、入力された runeEncodeRuneToString が返した値、そして期待される値が含まれており、デバッグに役立つ情報が提供されます。

このテストは、EncodeRuneToString が広範なUnicode文字に対して正確なUTF-8文字列を生成することを保証するために不可欠です。

関連リンク

このコミットはGo言語の初期のコミットであり、現在の unicode/utf8 パッケージの基礎を築いたものです。現在のGoの unicode/utf8 パッケージのドキュメントを参照すると、この機能がどのように進化し、他のUTF-8関連の関数と統合されているかを理解できます。

参考にした情報源リンク

  • Go言語の公式ドキュメント(stringruneUTF-8 に関する記述)
  • Go言語のソースコード(特に unicode/utf8 パッケージの歴史的な変更)
  • UTF-8のエンコーディングに関する一般的な情報
  • Go言語の初期の設計に関する議論(Goのブログやメーリングリストのアーカイブなど)
  • GitHubのコミット履歴とdiffビューア
  • Go言語の string 型と []byte 型の変換に関する情報