はじめに
前回のセクションでは、よく使われる数値型について解説しました。このセクションでは、Go 言語における文字型について学んでいきましょう。
学習ポイント:
- ASCII エンコーディング
- UTF-8 エンコーディング
- Unicode 文字セット
byte型rune型
ASCII エンコーディング
コンピュータの黎明期には、ASCII(American Standard Code for Information Interchange)というエンコーディング形式が使われていました。これは 7 ビットを使用して文字を表現し、128(2^7)種類の文字を扱うことができました。0 から 31 ビットおよび 127 ビットは表示できない制御文字を表し、32 から 126 ビットは日常的に使われる英大文字・小文字、数字、記号を表しています。詳細はこちらの表を参照してください。
コンピュータが普及するにつれ、さまざまな言語をサポートする必要が出てきました。しかし、ASCII エンコーディングでは不十分でした。その結果、簡体字中国語の GB2312、韓国語の EUC-KR、ロシア語の KOI8-R など、言語ごとに独自のエンコーディング形式が開発されました。
しかし、世界中に多くの言語が存在するため、すべての言語を統一できる単一のエンコーディング形式が必要となりました。そのニーズを満たすために誕生したのが Unicode です。
Unicode 文字セット
1991 年、Unicode コンソーシアムは Unicode 文字セットの最初のバージョンをリリースしました。その目的は、すべての言語を単一のエンコーディング形式に統合し、世界中のコンピュータがテキストをより簡単に表示・処理できるようにし、多言語環境での互換性の問題を回避することでした。
ただし、Unicode はあくまで「文字セット」であり、文字に対応するコードを定義しただけで、それらをどのようにメモリやディスクに保存するか(符号化方式)までは規定していませんでした。そのため、インターネットが普及するまでは、広く採用されるには至りませんでした。
UTF-8 エンコーディング
インターネットの継続的な発展に伴い、Unicode の実装エンコーディングである UTF-8 が普及しました。これは可変長エンコーディングであり、文字によってバイト長が異なるのが特徴です。
例えば、ASCII の範囲内にある英文字は 1 バイトで表現されます。文字 'y'(Unicode 値 121)は 1 バイトを占有します。
日常的に使われるほとんどの漢字は 3 バイトを占有します。例えば、「実」(Unicode 値 23454)という文字は 3 バイトです。
ただし、一部の漢字には 4 バイトを占有するものもあります。これは漢字が 10 万文字以上存在するのに対し、3 バイトでは約 6 万文字強しか表現できないため、少数の漢字には 4 バイトが必要になるからです。
UTF-8 エンコーディングのもう一つの利点は、ASCII エンコーディングと後方互換性があることです。実際、ASCII は UTF-8 のサブセットです。UTF-8 の最初の 128 文字は ASCII 文字と一対一で対応しています。つまり、もともと ASCII を使用していたソフトウェアは、ほとんど修正なしでそのまま使い続けることができます。これらの利点により、UTF-8 は徐々に推奨されるエンコーディング形式となりました。
Go 言語の生みの親である Rob Pike 氏と Ken Thompson 氏は、UTF-8 の考案者でもあります。そのため、Go は UTF-8 と非常に親和性が高い言語です。Go ではソースコードファイルを UTF-8 で保存することが義務付けられています。テキスト文字を操作する場合、UTF-8 エンコーディングが最適な選択肢となります。さらに、標準ライブラリには UTF-8 のエンコードとデコードに関する多くの関数が用意されています。
byte と rune
byte は uint8 の別名(エイリアス)であり、1 バイト(8 ビット)を占有します。ASCII テーブルにあるすべての文字を表現するのに適しています。しかし、byte が表現できる値の範囲は限られている(256 通り、つまり 2^8)ため、漢字のような複合的な文字を扱うには rune 型を使用する必要があります。
byte.go という新しいファイルを作成し、以下のコードを入力してください。
cd ~/project
touch byte.go
package main
import "fmt"
func main() {
var a byte = 76
fmt.Printf("Value of a: %c\n", a)
var b uint8 = 76
fmt.Printf("Value of b: %c\n", b)
var c byte = 'L'
fmt.Printf("Value of c: %c\n", c)
}
プログラムを実行すると、以下の結果が出力されます。
go run byte.go
Value of a: L
Value of b: L
Value of c: L
%c プレースホルダーは文字を出力するために使用されます。byte 型と uint8 型は、値が同じであれば同じ出力を生成することがわかります。ASCII テーブルを参照すると、文字 'A' の ASCII 値は 65 であることがわかります。整数プレースホルダー %d を使用して出力した場合も、値は 65 になります。
したがって、Go における byte は整数型の uint8 と等価であることが明らかです。同様のことが rune にも言えますが、こちらは異なる範囲の整数値を表します。
rune は int32 の別名であり、4 バイト(32 ビット)を占有します。これは、絵文字などの複合的な文字を表現するために使用されます。
byte.go ファイルを以下のコードで更新してください。
package main
import "fmt"
func main() {
var a rune = '😊' // 笑顔の絵文字
fmt.Printf("Value of a: %c\n", a)
var b int32 = 9829 // Unicode 文字の 10 進数表現(ハート記号)
fmt.Printf("Value of b: %c\n", b)
var c rune = 0x1F496 // Unicode 文字の 16 進数表現(輝くハートの絵文字)
fmt.Printf("Value of c: %c\n", c)
var d rune = '\u0041' // コードポイントによる Unicode 文字表現(大文字の 'A')
fmt.Printf("Value of d: %c\n", d)
var e rune = '\U0001F609' // コードポイントによる Unicode 文字表現(ウィンク顔の絵文字)
fmt.Printf("Value of e: %c\n", e)
}
プログラムを実行すると、以下の出力が表示されます。
go run byte.go
注意: プログラムはデスクトップまたは WebIDE のターミナルで実行してください。LabEx VM の上部にある「Terminal」タブでの実行は避けてください。
Value of a: 😊
Value of b: ♥
Value of c: 💖
Value of d: A
Value of e: 😉
- 変数
aは笑顔の絵文字 '😊' を表します。 - 変数
bは Unicode 文字の 10 進数表現(9829)で初期化されており、これはハート記号 '♥' に対応します。 - 変数
cは Unicode 文字の 16 進数表現(0x1F496)で初期化されており、これは輝くハートの絵文字 '💖' に対応します。 - 変数
dは\u0041という Unicode 形式を使用して大文字の 'A' を表します。 - 変数
eは\U形式とコードポイント0001F609を使用してウィンク顔の絵文字 '😉' を表します。
注意: Go 言語では、シングルクォート(' ')とダブルクォート(" ")は意味が異なります。シングルクォートは「文字」を表すために使用され、ダブルクォートは「文字列(string)」を宣言するために使用されます。したがって、byte 型や rune 型を宣言する際には必ずシングルクォートを使用してください。そうしないとエラーが発生します。
クイズ
学んだことを復習しましょう。rune.go という新しいファイルを作成し、以下のコードを入力してください。16 進数 0x1F648 を変数 a に代入し、プログラムがその値を正しく出力するようにコードを完成させてください。
- 要件:
rune.goファイルは~/projectディレクトリに配置してください。 - ヒント: 長い 16 進数のコードポイントを文字リテラルとして記述する場合、特定のフォーマットを使用する必要があります。
package main
import "fmt"
func main() {
var a rune = 0x1F648
fmt.Printf("The value of a is: %c\n", a)
}
まとめ
このセクションで学んだことを振り返りましょう。
- ASCII 文字は 1 バイトを占有し、128 種類の文字を表現できます。
- UTF-8 エンコーディングは Unicode 文字セットの一種です。可変長エンコーディングであり、表現する文字によってバイト長が異なります。
byteデータ型は ASCII 文字を表現するために使用され、runeデータ型は Unicode 文字を表現するために使用されます。byteはuint8の別名であり、runeはint32の別名です。
このセクションでは、まず ASCII、UTF-8、Unicode について説明しました。次に、文字データ型である byte および rune と、整数データ型との関係について解説しました。



