TonyBai · Go 语言进阶课
15
15
1.0x
00:00/00:00
登录|注册

05 | 字符串:不只是字节序列,揭秘rune、UTF-8与高效操作

你好,我是 Tony Bai。
在 Go 语言中,string 是我们几乎每天都要打交道的基本数据类型。但你是否真正理解它的“内心世界”?
Go 的字符串就像一首精妙的“二重奏”:有时,它表现为一串连续的字节(bytes),你可以对它进行索引、切片,就像操作字节数组一样;有时,它又展现为一串字符(characters),你可以用 for range 优雅地遍历其中的字符,无论它们占多少字节。
这种两面性是如何实现的呢?此外:
当我们处理包含中文、日文或其他非 ASCII 字符的文本时,如何确保正确性?
Go 是如何在底层表示字符串和字符的?rune 类型到底是什么?
UTF-8 编码在其中扮演了什么角色?
string 和 []byte 之间频繁转换,性能开销如何?Go 编译器又为我们做了哪些“零拷贝”优化?
拼接大量字符串时,用原生连接操作符 + 和用 strings.Builder 有多大差别?
如果你对这些问题还有模糊之处,那么这节课就是为你准备的。不深入理解字符串的“二重奏”本质,就可能在处理多语言文本时踩坑,或者在性能敏感的场景写出低效的代码。
这节课我们将深入学习 Go 字符串的内部实现、字符编码,以及如何高效地操作字符串,理解它“二重奏”的精髓。掌握了这些,你就能更自信、更高效地驾驭 Go 字符串这个强大的工具。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
  • 解释
  • 总结

1. Go 语言中的字符串具有两种视角:一种是字符串是字节序列,可以按字节索引和切片;另一种是字符串是字符序列,可以使用 for range 循环遍历每个 Unicode 字符。 2. 字符串底层是一个字节数组,而字符则是由 rune 类型表示的,rune 类型本质是一个 int32 类型,存储的是 Unicode 码点。 3. Go 字符串并没有直接存储码点,而是将码点进行了编码,然后存储编码后的字节序列,采用的编码方式是 UTF-8。 4. 在处理包含中文、日文或其他非 ASCII 字符的文本时,需要确保正确性,可以使用标准库 unicode/utf8 中的函数来精确计算字符数量、进行 utf8 编解码等。 5. 字符串的不可变性使得多个字符串变量可以共享同一个底层字节数组,节省内存空间。 6. 在拼接大量字符串时,使用原生连接操作符 “+” 和使用 strings.Builder 有较大差别,strings.Builder 更高效。 7. Go 编译器在特定场景下会对字符串和字节切片之间的转换进行优化,避免不必要的数据拷贝,提高程序的性能和效率。 8. 使用 strings.Builder 类型进行字符串拼接可以避免频繁的内存分配和拷贝操作,提高性能. 9. Go 1.21 引入了新的 unsafe 函数,提供了更清晰的 API,用于执行之前需要使用 reflect.StringHeader 和 reflect.SliceHeader 的操作,实现零拷贝的转换. 10. 应优先依赖编译器优化,避免使用 `unsafe` 进行强制零拷贝,除非极度必要且能控制风险。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《TonyBai · Go 语言进阶课》
新⼈⾸单¥59
立即购买
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部