Go-03-字符串处理与字符编码
本节目标:掌握 Go 字符串的常见操作(查找、替换、截断、拆分),理解 byte / rune / string 三者的关系,并搞懂 UTF-8 编码在 Go 中的处理方式。
1. 字符串的本质
Go 的字符串是不可变的字节序列(不是字符序列!)。字符串字面量用双引号或反引号:
1 | s1 := "Hello\n世界" // 双引号:支持转义 |
字符串的内部结构:type string struct { Data uintptr; Len int },只读。
字符串可以用 == < + 拼接(但 + 拼接会产生新字符串,老字符串不变):
1 | s := "hello" + " " + "world" |
**高效拼接用 strings.Builder 或 fmt.Sprintf**:
1 | import "strings" |
2. byte / rune / string 的三角关系
这是 Go 字符串处理最关键的概念:
string= UTF-8 编码的字节序列[]byte= string 的底层字节(mutate 后转回 string 就是新字符串)[]rune= string 解码后的 Unicode 码点序列byte=uint8的别名rune=int32的别名,专门表示一个 Unicode 码点
1 | s := "Hello, 世界" |
关键点:
len(s)返回字节数,不是字符数range s遍历时,索引 i 是字节偏移,不是字符序号- 要按字符处理,先用
[]rune(s)转换
3. 常见字符串操作(strings 包)
3.1 包含、查找
1 | import "strings" |
3.2 大小写转换
1 | fmt.Println(strings.ToUpper("Hello")) // "HELLO" |
3.3 修剪(trim)
1 | s := " Hello, World " |
3.4 替换
1 | s := "I love Go, Go is great" |
3.5 拆分与拼接
1 | s := "a,b,c,d" |
3.6 比较
1 | // == 是字节比较,对 ASCII 没问题,对带大小写/变音符号的 Unicode 字符会出错 |
4. 字符串与数字转换(strconv)
1 | import "strconv" |
5. 修改字符串
字符串不可变,要”修改”得先转 []byte 或 []rune:
1 | s := "hello" |
6. UTF-8 编码基础
UTF-8 是变长编码:
- ASCII 字符(U+0000 ~ U+007F):1 字节
- 拉丁字母(U+0080 ~ U+07FF):2 字节
- BMP 字符(含中文,U+0800 ~ U+FFFF):3 字节
- 辅助平面字符(U+10000 ~ U+10FFFF):4 字节
1 | fmt.Println(utf8.RuneCountInString("Hello")) // 5 |
最常见的坑:把字符串当字符数组遍历:
1 | s := "你好世界" |
正确做法:用 utf8.RuneCountInString 数字符,用 []rune(s) 转 rune 切片。
7. 实战:统计字符串中的中文字数
1 | package main |
8. 实战:判断一个字符串是否是回文(按字符)
1 | package main |
小结
| 操作 | 字节视角([]byte) |
字符视角([]rune) |
|---|---|---|
| 长度 | len(s) |
utf8.RuneCountInString(s) |
| 遍历 | for i := 0; i < len(s); i++ |
for i, r := range s |
| 子串 | s[i:j](按字节切,可能乱码) |
string([]rune(s)[i:j]) |
| 索引 | s[i] 拿一个字节 |
[]rune(s)[i] 拿一个字符 |
黄金法则:
- 字符串 = UTF-8 字节序列
- 中文字符处理 →
[]rune或range - 大小写不敏感比较 →
strings.EqualFold - 数字字符串互转 →
strconv包 - 拼接大量字符串 →
strings.Builder
下一节进入面向对象:Go 没有 class,但有 struct + method + interface,写起来比 class 更简洁。
- 本文作者: CoderSong
- 本文链接: https://jack-song-gif.github.io/2026/08/30/Go-03-字符串与字符编码/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!