メインコンテンツにスキップ
モジュール 4 · レッスン 4 / 5コース内の 19/50~12 min
モジュールのレッスン (4/5)

文字列、バイト、ルーン

Go では、string は 不変なバイト シーケンスです。文字列リテラル UTF-8 でエンコードされます。 rune は int32 のエイリアスであり、 は単一の Unicode コード ポイントを表します。

バイトとルーンの違いを理解することは不可欠です 文字列にアクセント、絵文字、表意文字などが含まれる場合のバグを回避します。 非 ASCII 文字。

string = 文字ではなくバイト

Go
s := "ciaò"
fmt.Println(len(s))   // 5 — not 4!
fmt.Println(s[0])     // 99 ('c' as a byte)
fmt.Println(s[3])     // 195 (first byte of 'ò' in UTF-8)

len(s) は、表示される文字ではなく バイト の数を返します。 s[i] のインデックスを作成すると、文字ではなく i 番目のバイト (uint8) が返されます。

for range ルーンを反復します

for i, r := range s は UTF-8 をオンザフライでデコードします。 i はバイト オフセットです。 ルーンの先頭の r はルーン (int32) です。

Go
s := "ciaò"
for i, r := range s {
    fmt.Printf("%d %c (U+%04X)\n", i, r, r)
}
// 0 c (U+0063)
// 1 i (U+0069)
// 2 a (U+0061)
// 3 ò (U+00F2)   <- starts at byte 3, takes 2 bytes

[]rune(s): 文字ごとのインデックス作成

明示的な変換: ルーンの新しいスライスを割り当てます。費用はかかりますが、 時には必要なこともあります:

Go
runes := []rune("ciaò")
fmt.Println(len(runes))    // 4
fmt.Println(string(runes[3])) // ò

string(runes) は逆変換です。[]rune を受け取り、 UTF-8文字列。

文字列は不変です

Go
s := "ciao"
// s[0] = 'C'   // ERROR: cannot assign to s[0]

変更するには、[]byte または []rune に変換し、操作して、元に変換します。

Go
b := []byte(s)
b[0] = 'C'
s = string(b)   // "Ciao"

連結

+ 演算子は機能しますが、ループ内の多くの連結では次を使用します。 strings.Builder (より効率的、中間割り当てを回避):

Go
var sb strings.Builder
for i := 0; i < 5; i++ {
    sb.WriteString("ab")
}
fmt.Println(sb.String())   // "ababababab"

便利なパッケージ

  • strings: Contains、HasPrefix、Split、Join、ToUpper、Replace...
  • strconv: Atoi、Itoa、ParseFloat、FormatInt...
  • unicode: IsLetter、IsDigit、ToUpper...
  • unicode/utf8: RuneCountInString (len([]rune(s)) の代替)。

試してみてください

運動#go.m4.l4.e1
試行回数: 0読み込み中…

範囲を指定して文字列 s を反復し、%d %c を使用してインデックスとルーンを出力します。

エディターを読み込み中…
ヒントを表示

文字列の範囲はバイトオフセット + ルーンを返します。

3 回の試行後に解決策が利用可能になります

運動#go.m4.l4.e2
試行回数: 0読み込み中…

s を []rune に変換し、その長さを文字数で出力します。

エディターを読み込み中…
ヒントを表示

明示的な変換: `[]rune(s)`。

3 回の試行後に解決策が利用可能になります

Quiz#go.m4.l4.e3
準備完了

len("ciaò") とは何ですか?

Go
s := "ciaò"
fmt.Println(len(s))
回答の選択肢

要約

  • string = UTF-8 でエンコードされた不変のバイト シーケンス。
  • len(s) = バイト; s[i] = i 番目のバイト (uint8)。
  • for i, r := range s はルーン文字を解読します。 i はバイト オフセットです。
  • []rune(s) 文字ごとにインデックスを作成します (コストがかかり、割り当てが行われます)。
  • 変更するには: []byte または []rune を実行します。
  • ループ内で連結するには: strings.Builder。
  • 主要パッケージ: strings、strconv、unicode、unicode/utf8。