1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

文字列

Goの文字列はイミュータブルなデータ構造

  • イミュータブルなバイト列へのポインタ
  • そのバイト列内のバイトの総数

rune

  • 文字セット : 文字の集合。Unicodeの文字セットは $ 2^{21} $個ある
  • エンコーディング : 文字のリストを2進数で翻訳したもの。UTF-8は全てのUnicode文字を可変なバイト数(1~4byte)でエンコーディングできるエンコーディング規格

code pointとは、unicodeで1つの値で表される項目を指す。「漢」は、U+6f22コードポイントで識別される。UTF-8では、「漢」は0xE6, 0xBC, 0xACの3バイトでエンコードされる。runeはUnicodeのコードポイントである。
Unicodeのコードポイントは21ビットで、コードポイントを保持するためのruneはint32のエイリアスとなる。

type rune = int 32

以下は文字リテラル(文字列定数)を代入している。

s := "hello"

Goでは、ソースコードはUTF-8でエンコードされる。文字列リテラルは全てUTF-8でバイト列にエンコードされる。しかし、文字列は任意のバイト列であり、UTF-8であるわけではない。文字リテラルで初期化されていない変数を操作する場合(ファイルシステムから読み込む等)、必ずしもUTF-8エンコーディングを使っているとは限らない。

golang.org/xは、標準ライブラリに対する拡張を提供するリポジトリで、UTF-16とUTF-32を扱うたのパッケージを含む

1文字は常に1バイトにエンコードされるわけではない。

s := "hello"
fmt.Println(len(s)) // 5
s := "漢"
fmt.Println(len(s)) // 3

"漢"という文字は、0xE6,0xBC, 0xA2という2バイトで構成される。

func main() {
	s := string([]byte{0xE6, 0xBC, 0xA2})
	fmt.Println(s) // 漢
}

func main() {
	s := "hêllo"
	for i := range s {
		fmt.Printf("position %d: %c\n", i, s[i])
	}
	fmt.Printf("len=%d\n", len(s))
}

これを実行すると、以下のようになる。

実行結果
position 0: h
position 1: Ã
position 3: l
position 4: l
position 5: o
len=6

特殊文字êをUTF-8にエンコードすると、c3 aaとなる。
また、c3Ãとなる。

この解決法としては、rangeを使用する。

func main() {
	s := "hêllo"
	for i, r := range s {
		fmt.Printf("position %d: %c\n", i, r)
	}
}

実行すると、ちゃんとhêlloが出力される。

実行結果
position 0: h
position 1: ê
position 3: l
position 4: l
position 5: o

ただし、indexはやはり、2が飛ばされている。

もう一つの方法として、以下のように文字列をスライスにする方法がある。

func main() {
	s := "hêllo"
	runes := []rune(s)
	for i, r := range runes {
		fmt.Printf("position %d: %c\n", i, r)
	}
}

これを実行すると、

実行結果
position 0: h
position 1: ê
position 2: l
position 3: l
position 4: o

ただし、この解決法は、実行時のオーバーヘッドが発生する。文字列をルーンのスライスに変換するには、追加のスライスを割り当て、バイトをルーンに変換しなければならなく、時間計算量はO(n)となる。なので、できる限り最初の解決法で行う方が良い。

indexでアクセスしたい場合は、以下のようにする。

func main() {
	s := "hêllo"
	r := []rune(s)[4]
	fmt.Printf("%c\n", r) // o
}

スライド

参考文献

  1. Japanese Version - 100 Go Mistakes and How to Avoid Them
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?