Characters and Strings

在Go语言中,字符可以由两种方式表示。单个字符可以由单个rune(or int32)表示。 从现在开始我们使用专业术语"Character", "Code point", "Unicode character" 和 "Unicode code point" 表示单个字符。 Go strings是由0个或者多个characters组成的字符序列。在一个字符串中每一个字符又是由一个或者多个UTF-8编码过的字节(bytes)组成。

我们可以将单个字符,对过string(char)转换为只有一个字符的字符串。 如下所示

æs := ""
for _, char := range []rune{'æ', 0xE6, 0346, 230, '\xE6', '\u00E6'} {
fmt.Printf("[0x%X '%c'] ", char, char)
æs += string(char)
}
[0xE6 'æ'][0xE6 'æ'][0xE6 'æ'][0xE6 'æ'][0xE6 'æ'][0xE6 'æ']

一个字符串可以通过chars := []rune(s)的语法转换为rune slice. 这对于我们需要挨个解析每个字符时非常有用。 相反的操作是 s := string(chars) 将一个[]rune或才[]int32 slice转换为字符串。 这种转换的时间是0(n).

字符串连接可以使用最方便, 最简单的 string += 的方式,但这种方式的效率最低,一种更好的方式是像Python那样,一次性把所有的字符串存入一个字符串数组,然后通过strings.Join()函数,连接各个字符串.Go还提供了一种更好的方法, 类似于Java's StringBuilder.

æs := []string{"hello", "中国", "开发语言"}
fmt.Println(strings.Join(æs, "test"))
var buffer bytes.Buffer     //创建一个空的bytes.Buffer
for {
    if piece, ok := getNextValidString(); ok {
        buffer.WriteString(piece) //通过WriteString将字符串写入buffer
    } else {
        break
        }
}
fmt.Print(buffer.String(), "\n")//String()取出字符串

bytes.Buffer要比 +=运算符更有效率,但也占用更多的内存和CPU.

for ... range loop 可以用于character by character遍历字符串。每一次遍历生成一个index和代码点(code point).

phrase := "vått og tørt"
fmt.Printf("strings: %s\n", phrase)
fmt.Println("index rune    char bytes")
for index, char := range phrase { 
// for ... range 会对UTF-8字节数组解码为 Unicode字符码(runes).
fmt.Printf("%-2d    %U  '%c'  % X\n", index, 
char, char, []byte(string(char)))
//获得bytes, 我们先需要将单个char, 转化为string(获得UTF-8的编码字节),在将这单个字符的字符串,转变为 bytes
strings: vått og tørt
index rune    char bytes
0     U+0076  'v'  76
1     U+00E5  'å'  C3 A5
3     U+0074  't'  74
4     U+0074  't'  74
5     U+0020  ' '  20
6     U+006F  'o'  6F
7     U+0067  'g'  67
8     U+0020  ' '  20
9     U+0074  't'  74
10    U+00F8  'ø'  C3 B8
12    U+0072  'r'  72
13    U+0074  't'  74

为了获得每个字符的字节,我们先将code point(rune)转换为string. 然后将这个只有单个字符的字符串转换为[]byte slice, 这样我们才能真正的访问实现的字节bytes. []byte(string)的转换非常快(0(1)).