Go by Example:字串與符文

Go 字串是唯讀位元組切片。Go 語言和標準函式庫特別將字串視為以 UTF-8 編碼之文字容器。在其他語言中,字串由「字元」構成。在 Go 中,「字元」的概念稱為 rune,這個整數代表一個 Unicode 編碼點。這篇 Go 部落格文章 有不錯的入門介紹。

package main
import (
    "fmt"
    "unicode/utf8"
)
func main() {

s 是一個 string,其指派的值代表泰文中的「hello」。Go 字串字面值是 UTF-8 編碼文字。

    const s = "สวัสดี"

由於字串等同於 []byte,這會傳回儲存在內部的原始位元組長度。

    fmt.Println("Len:", len(s))

編制字串索引可產生每個索引的原始位元組值。這個迴圈會產生構成 s 中碼點的所有位元組的十六進位值。

    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 迴圈會特別處理字串,並解碼字串中的各個 符文 及其在字串中的偏移量。

    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

此處示範如何將 符文 值傳遞給函式。

        examineRune(runeValue)
    }
}
func examineRune(r rune) {

使用單引號括起來的值為 符文字面值。我們可以直接比較 符文 值與符文字面值。

    if r == 't' {
        fmt.Println("found tee")
    } else if r == 'ส' {
        fmt.Println("found so sua")
    }
}
$ 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

下一範例:結構