【Go 简明手册】Go基本语法——字符串

Go 语言中的字符串是 UTF-8 字符的一个序列(当字符为 ASCII 码时则占用 1 个字节,其它字符根据需要占用 2-4 个字节)。UTF-8 是被广泛使用的编码格式,是文本文件的标准编码,其它包括 XML 和 JSON 在内,也都使用该编码。由于该编码对占用字节长度的不定性,Go 中的字符串也可能根据需要占用 1 至 4 个字节,这与其它语言如 C++、Java 或者 Python 不同。Go 这样做的好处是不仅减少了内存和硬盘空间占用,同时也不用像其它语言那样需要对使用 UTF-8 字符集的文本进行编码和解码。

Go 语言中字符串的可以使用双引号 (") 或者反引号 (`) 来创建。双引号用来创建可解析的字符串字面量,所谓可解析的是指字符串中的一些符号可以被格式化为其他内容,如 \n 在在输出时候会被格式化成换行符,如果需要按照原始字符输出必须进行转义。而反引号创建的字符串原始是什么样,那输出还是什么,不需要进行任何转义。以下是几个例子:

1
2
3
t1 := "\"hello\""             //内容: "hello"
t2 := `"hello"` //内容:和t1一致
t3 := "\u6B22\u8FCE" //内容:欢迎

Go 语言中的部分转义字符如下表所示:

转义字符 含义
\\ 表示反斜线
\' 单引号
\" 双引号
\n 换行符
\uhhhh 4 个 16 进制数字给定的 Unicode 字符

在 Go 语言中单个字符可以使用单引号 (') 来创建。之前的课程中,我们有学习过 rune 类型,它等同于 int32,在 Go 语言中,一个单一的字符可以用一个单一的 rune 来表示。这也是容易理解的,因为 Go 语言的字符串是 UTF-8 编码,其底层使用 4 个字节表示,也就是 32 bit。

在 Go 语言中,字符串支持切片操作,但是需要注意的是如果字符串都是由 ASCII 字符组成,那可以随便使用切片进行操作,但是如果字符串中包含其他非 ASCII 字符,直接使用切片获取想要的单个字符时需要十分小心,因为对字符串直接使用切片时是通过字节进行索引的,但是非 ASCII 字符在内存中可能不是由一个字节组成。如果想对字符串中字符依次访问,可以使用 range 操作符。另外获取字符串的长度可能有两种含义,一种是指获取字符串的字节长度,一种是指获取字符串的字符数量。字符串支持以下操作:

语法 描述
s += t 将字符串 t 追加到 s 末尾
s + t 将字符串 s 和 t 级联
s[n] 从字符串 s 中索引位置为 n 处的原始字节
s[n:m] 从位置 n 到位置 m-1 处取得的字符(字节)串
s[n:] 从位置 n 到位置 len(s)-1 处取得的字符(字节)串
s[:m] 从位置 0 到位置 m-1 处取得的字符(字节)串
len(s) 字符串 s 中的字节数
len([]rune(s)) 字符串 s 中字符的个数,可以使用更快的方法 utf8.RuneCountInString()
[]rune(s) 将字符串 s 转换为一个 unicode 值组成的串
string(chars) chars 类型是 []rune 或者 []int32, 将之转换为字符串
[]byte(s) 无副本的将字符串 s 转换为一个原始的字节的切片数组,不保证转换的字节是合法的 UTF-8 编码字节

让我们尝试一个例子,创建源文件 string_t.go,然后输入以下源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"fmt"
)

func main() {
t0 := "\u6B22\u8FCE\u6765\u5230" // t0内容:欢迎来到
t1 := "\u5B9E\u9A8C\u697C" // t1内容:实验楼
t2 := t0 + t1
for index, char := range t2 {
fmt.Printf("%-2d %U '%c' %X %d\n",
index, char, char, []byte(string(char)), len([]byte(string(char))))
}
fmt.Printf("length of t0: %d, t1: %d, t2: %d\n", len(t0), len(t1), len(t2))
fmt.Printf("content of t2[0:2] is: %X\n", t2[0:2])
}

然后通过以下方式运行,在这里一起显示了程序的输出:

1
2
3
4
5
6
7
8
9
10
$ go run string_t.go
0 U+6B22 '欢' E6ACA2 3
3 U+8FCE '迎' E8BF8E 3
6 U+6765 '来' E69DA5 3
9 U+5230 '到' E588B0 3
12 U+5B9E '实' E5AE9E 3
15 U+9A8C '验' E9AA8C 3
18 U+697C '楼' E6A5BC 3
length of t0: 12, t1: 9, t2: 21
content of t2[0:2] is: E6AC

说明:

通过前面的课程我们知道通过 \uhhhh 的方式我们可以通过创建 Unicode 字符。

在以上程序中,首先通过 := 符号创建了变量 t0,其值为 \u6B22\u8FCE\u6765\u5230,是 欢迎来到 中文字符的 unicode 编码,然后以同样的方式创建了变量 t1,其值为 实验楼,然后通过 + 操作符将 t0 和t1 拼接赋值给 t2。然后我们通过 range 操作符号对 unicode 字符串 t2 中的每一个 unicode 字符依次操作,我们这里只是简单的打印出每个字符在 t2 中的位置,每个字符的 unicode 码值,每个字符的字面量,每个字符的十六进制值,以及每个字符的字节长度。

这里我们使用 fmt 包种支持的格式指令,如果读者学习过 C 语言的话就一目了然。接着,我们通过 len 操作符计算出了每个字符串的字节长度。最后,我们使用切片访问了字符串 t2 的第 0-1 个字节,也就是前两个字节,其内容为 E6AC。前面我们说到不能使用切片的方式访问非 ASCII 字符串中的字符,原因在这里一目了然。字符 欢 其底层使用了三个字节表示,内容是 E6ACA2,如果只是简单的使用切片(只取切片中的一项)访问的是不能访问到整个字符的,因为字符的切片是通过字节数来索引的。


【Go 简明手册】Go基本语法——字符串
https://hodlyounger.github.io/B_Code/GO/Go简明手册/Go语言基础/字符串/【Go简明手册】字符串/
作者
mingming
发布于
2023年10月27日
许可协议