以下文章翻译自罗伯·派克发表在Go Blog的文章,文章中为读者详述了Go语言中字符串与我们经常提起的字节、字符还有rune的关系和相互之间的不同。正如派克在文中所说
字符串这个话题对于一篇博客文章来说似乎太简单了,但是要很好地使用它们,不仅需要了解它们的工作原理,还需要了解字节,字符和 rune 的区别,以及 Unicode 和 UTF- 8,字符串和字符串直接量之间的区别,以及其他甚至更细微的区别。
原文地址: https:// blog.golang.org/strings
文章篇幅还是挺长的,大家时间都很宝贵所以我先把文章探究的问题的结论放在前面,有时间的同学还是建议整篇读一下。
- Go 源代码始终为 UTF-8。
- 字符串可以包含任意字节。
- 字符串文字中不包含字节级转义符时字符串始终包含有效的 UTF-8 序列。
- 代表 Unicode 码点的字节序列称为
rune
。 - 在 Go 中不会保证字符串中的字符被规范化。
原文的语法、句式都很好学习Go 语言的同时还能加强一下英文阅读推荐去读英文原文,有翻译不清楚的欢迎指正。
介绍
上一篇博客文章使用许多示例说明了切片在其实现背后的机制,从而说明了切片在 Go 中的工作方式。以此为背景,本文会讨论 Go 中的字符串。一开始会让人觉得,字符串这个话题对于一篇博客文章来说似乎太简单了,但是要很好地使用它们,不仅需要了解它们的工作原理,还需要了解字节,字符和 rune
的区别,以及 Unicode 和 UTF- 8,字符串和字符串直接量之间的区别,以及其他甚至更细微的区别。
展开讨论这个话题的一种方法是将其视为对以下常见问题的解答:“当我索引 Go 字符串时,在 n 个位置为什么没有得到第 n 个字符?” 如您所见,这个问题将我们引向了许多文本在现实世界中是如何工作的细节中。
独立于 Go 语言之外,Joel Spolsky 的著名博客文章绝对绝对是每个软件开发人员绝对绝对肯定地了解 Unicode 和字符集 (无借口!) 很好地介绍了这些问题的细节。他提出的许多观点将在这里进行阐述。
什么是字符串?
让我们从一些基础知识开始。
在 Go 中,字符串实际上是只读的字节切片。如果你完全不知道一个字节切片是什么以及它是如何工作的,请阅读上一篇博客文章 ; 我们在这里假设你已经知道这些。
预先说明字符串可以包含任意字节很重要,字符串没有规定只能包含 Unicode 文本,UTF-8 文本或任何其他预定义格式。就字符串的内容而言,它完全相当于一个字节切片。
下面一个字符串文字 (稍后将进一步介绍),该文字使用.NN
表示法定义了一个包含某些特殊字节值的字符串常量。 (当然,一个字节的范围是十六进制值 00 到 FF)。
const sample =“ .bd.b2.3d.bc.20.e2.8c.98”
打印字符串
由于字符串常量 sample
中的某些字节不是有效的 ASCII,甚至不是有效的 UTF-8,因此直接打印字符串将产生诡异的输出。下面使用简单的打印语句打印 sample
fmt.Println(sample)
输出这一堆乱码(输出会因运行环境不同而有所不同)
��=� ⌘
要找出该字符串真正包含了什么,我们需要将其分解并检查每一部分。有几种方法可以做到这一点。最明显的是遍历其内容并单独取出每个字节,如以下 for
循环所示
for i := 0; i < len(sample); i++ {
fmt.Printf("%x ", sample[i])
}