Skip to content

Instantly share code, notes, and snippets.

@minoritea
Last active June 8, 2016 10:46
Show Gist options
  • Save minoritea/22588f481c938fac5dcddf1659271157 to your computer and use it in GitHub Desktop.
Save minoritea/22588f481c938fac5dcddf1659271157 to your computer and use it in GitHub Desktop.

基本型(2)

3.5, 文字列型

文字列はイミュータブルなバイト列である。 文字列はNULL文字を含む任意のデータであるが、通常はヒューマンリーダブルなテキストを表すのに使われる。 テキストはUTF-8でエンコードされたユニコード・コードポイント(Rune)の連なりとして解釈される。

len関数は文字列のバイト長を返す(Runeの数ではない)。 インデックス操作(s[i])は文字列sのi番目のバイトを返す。 文字列のインデックスの範囲(0 <= i < len(s))を超えてアクセスした場合はパニックとなる。

s[i:j]はインデックスiのバイトからインデックスjより前のバイトを含む部分文字列となる。

インデックスが範囲外になったり、j < iのときにはパニックとなる。

i,jのオペランドは省略できる。 省略した場合のデフォルト値は

  • i = 0
  • j = len(s)

である。

+演算子は二つの文字列を連結した新しい文字列を作成する。

文字列は==<のような比較演算子で比較できる。 比較はバイト単位で行われるので、比較結果は辞書順に従う。

文字列はイミュータブルなので、値を変更することはできない。 変数に新しい値を割り当てることはできる。

s := "left foot"
t := "s"
s += ", right foot"

上記は元の文字列を変更しないが、+=ステートメントにより新しい文字列を割り当てる。 tの値は変わらない。

s[0] = 'L'

上記のように文字列の一部を再割り当てすることはできない。

不変性のため、二つの文字列のコピーを同じメモリ上の領域で安全に共有できる。 そのため文字列のコピーは低コストである。 同じく、部分文字列は安全に元の文字列と同じデータを共有することが出来るため、 部分文字列の作成も低コストでできる。 新しいメモリ上の領域はアロケートされない。

3.5.1. 文字列リテラル

文字列はダブルクォートで囲まれたバイト列(文字列リテラル)で表現できる。

Goのソースファイルは常にUTF-8でエンコードされており、文字列は常にUTF-8のため、 文字列リテラルにはユニコード・コードポイントを含めることが出来る。

ダブルクォートされた文字列リテラル中で、 \から始まるエスケープ・シーケンスは任意のバイト値を挿入するのに用いられる。

  • \a = ベル
  • \b = バックスペース
  • \f = フォームフィード
  • \n = 改行
  • \r = キャリッジリターン
  • \t = タブ
  • \v = 垂直タブ
  • \' = シングルクォート(Runeリテラルで用いられる)
  • \" = ダブルクォート
  • \\ = バックスラッシュ

任意のバイトを16進数もしくは8進数のエスケープで表すことが出来る。

  • \xhh = hを16進数としたとき換算されるバイトの文字
  • \ooo = oを8進数としたとき換算されるバイトの文字

ユニコード・コードポイントについては後で扱う。

生の文字列リテラルはバッククォートで囲まれたバイト列で表される。 生の文字列リテラルはそのままコンテンツを保持する。 バックスラッシュや改行を含んでもよい。つまり複数行文字列も表すことが出来る。 プラットフォームで挙動を共通にするため、キャリッジリターンは自動で取り除かれる。

3.5.2. ユニコード

その昔、人生はシンプルで、そこには -- 少なくとも狭い視野の中では -- たった一つのキャラクターセットと取り組むことだけでよかった。それはASCIIである。 (原文直訳)

現在において、多様な言語に対応するためには、ユニコードが用いられる。 ユニコード文字はユニコード・コードポイントと呼ばれる数がそれぞれ割り当てられてる。 Goの世界ではそれをRuneと呼ぶ。

ユニコードのバージョン8は、12万文字のコードポイントを定義している。 runeはint32のシノニムである。

つまりRuneの連なりはint32の値の列として考えることもできる。 それはUTF-32,UCS-4と呼ばれるもので、それぞれのユニコード・コードポイントは同じ大きさを持つ(32bit)。 UTF-32は一つの文字につき32bitを使うのでASCIIに対してより多くの領域を使う。

3.5.3. UTF-8

UTF-8はユニコード・コードポイントの可変長のエンコーディングである。 UTF-8はケン・トンプソンとロブ・パイクによって創始され(二人ともGoの作者でもある)、 現在ではユニコードにおける標準の一つでもある。

それぞれのRuneを表現するのに1~4バイトを使うが、1バイトはASCII文字列として、 2~3バイトの場合のみ広く使われる文字を表すのに使われる。 最初のバイトの最上位のビット列はいくつのバイトが続くかを表している。 最上位が0の場合、そのバイトは7bit ASCIIである。 例えば最上位が110の場合runeは2バイトで表され、二番目のバイトは10から始まる。

可変長エンコーディングではn番目の文字に直接インデックスでアクセスすることは出来ない。 しかしUTF8はそれらを補う特質を多く備えている。文字の始まりを見つけるのに3バイト以上後退する必要はない。 プレフィックスでコードされているのであいまいさや先読みなしに左から右にデコードできる。 runeは他のruneの部分文字列ではないのであるruneを見つけるには対応するバイト列をそのまま検索すれば良い。 ユニコードを辞書順に並べるとコードポイント順に並ぶので、UTF-8のソートは普通に処理出来る。 ヌル文字をバイト列中に含むことがないので ヌルを終端文字とするプログラミング言語にとって便利である。

Goのソースファイルは常にUTF8でエンコードされており、また、Goプログラムでテキストを扱う際にはUTF8でエンコードされていることが望ましい。

unicodeパッケージはrune単体を扱うのに用いられる(文字と数字を区別したり、大文字と小文字を変換するなどに用いられる)。 unicode/utf8パッケージはバイト列とRune列をエンコード/デコードために用いられる。

ユニコード文字の多くはキーボードでタイプするのが難しく、また視覚的に判別するのが難しい。 文字列リテラル中のユニコード・エスケープはそれらをコードポイント値で扱うことにすることができる。 エスケープは二つ種類があり、\uhhhhは16ビットの値を、\uhhhhhhhhは32ビットの値を表すのに用いられる。 hは16進数の数字である。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment