はじめに
この実験では、Go 言語の文字列とルーンに焦点を当てています。Go 言語では、文字列はバイトの読み取り専用スライスであり、ルーンは Unicode コードポイントを表す整数です。この実験では、Go 言語で文字列とルーンを扱う方法を探ります。
文字列とルーン
この実験で解決する問題は、Go 言語で文字列とルーンを扱う方法を理解することです。具体的には、文字列の長さを取得する方法、文字列のインデックスにアクセスする方法、文字列内のルーンの数をカウントする方法、および文字列内のルーンを反復処理する方法をカバーします。
この実験を完了するには、以下が必要です。
- Go 言語の構文の基本的な理解
- Go 言語の文字列とルーンの知識
- Go 言語の標準ライブラリ
$ go run strings-and-runes.go
Len: 18
e0 b8 aa e0 b8 a7 e0 b8 b1 e0 b8 aa e0 b8 94 e0 b8 b5
Rune count: 6
U+0E2A 'ส' starts at 0
U+0E27 'ว' starts at 3
U+0E31 'ั' starts at 6
U+0E2A 'ส' starts at 9
U+0E14 'ด' starts at 12
U+0E35 'ี' starts at 15
Using DecodeRuneInString
U+0E2A 'ส' starts at 0
found so sua
U+0E27 'ว' starts at 3
U+0E31 'ั' starts at 6
U+0E2A 'ส' starts at 9
found so sua
U+0E14 'ด' starts at 12
U+0E35 'ี' starts at 15
以下に完全なコードがあります。
// Go 言語の文字列は、バイトの読み取り専用スライスです。この言語と
// 標準ライブラリは、文字列に特別な扱いを行います。
// [UTF-8](https://en.wikipedia.org/wiki/UTF-8) でエンコードされた
// テキストのコンテナとしてです。
// 他の言語では、文字列は「文字」で構成されています。
// Go 言語では、文字の概念は `rune` と呼ばれます。これは、
// Unicode コードポイントを表す整数です。
// [この Go 言語のブログ記事](https://go.dev/blog/strings) は、
// このトピックの良い紹介になっています。
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
// `s` は、タイ語の「こんにちは」を表すリテラル値が割り当てられた
// `string` です。Go 言語の文字列リテラルは UTF-8 でエンコードされた
// テキストです。
const s = "สวัสดี"
// 文字列は `[]byte` に等しいため、これは格納されている生のバイトの
// 長さを生成します。
fmt.Println("Len:", len(s))
// 文字列にインデックスを付けると、各インデックスにある生のバイト値が
// 生成されます。このループは、`s` のコードポイントを構成するすべての
// バイトの 16 進数値を生成します。
for i := 0; i < len(s); i++ {
fmt.Printf("%x ", s[i])
}
fmt.Println()
// 文字列内のルーンの数をカウントするには、`utf8` パッケージを使用できます。
// ただし、`RuneCountInString` の実行時間は文字列のサイズに依存します。
// なぜなら、各 UTF-8 ルーンを順次デコードする必要があるからです。
// 一部のタイ文字は複数の UTF-8 コードポイントで表されるため、
// このカウントの結果は予想外になる場合があります。
fmt.Println("Rune count:", utf8.RuneCountInString(s))
// `range` ループは、文字列を特別に扱い、各 `rune` とその文字列内の
// オフセットをデコードします。
for idx, runeValue := range s {
fmt.Printf("%#U starts at %d\n", runeValue, idx)
}
// 明示的に `utf8.DecodeRuneInString` 関数を使用することで、
// 同じ反復処理を達成できます。
fmt.Println("\nUsing DecodeRuneInString")
for i, w := 0, 0; i < len(s); i += w {
runeValue, width := utf8.DecodeRuneInString(s[i:])
fmt.Printf("%#U starts at %d\n", runeValue, i)
w = width
// これは、`rune` 値を関数に渡すことを示しています。
examineRune(runeValue)
}
}
func examineRune(r rune) {
// シングルクォートで囲まれた値は、「ルーンリテラル」です。
// 直接、`rune` 値とルーンリテラルを比較できます。
if r == 't' {
fmt.Println("found tee")
} else if r == 'ส' {
fmt.Println("found so sua")
}
}
まとめ
この実験では、Go 言語の文字列とルーンを扱う方法について説明しました。文字列の長さを取得する方法、文字列にインデックスを付ける方法、文字列内のルーンの数をカウントする方法、および文字列内のルーンを反復処理する方法を示しました。この実験を完了することで、Go 言語で文字列とルーンを扱う方法をより深く理解するはずです。