string
Go 中的值存储为只读字节片([]byte
),其中字节是 ( 的 UTF-8 编码字节rune
的)string
. UTF-8 https://en.wikipedia.org/wiki/UTF-8是一种可变长度编码,不同的 Unicode 代码点可以使用不同数量的字节进行编码。例如范围内的值0..127
被编码为单个字节(其值是 unicode 代码点本身),但大于 127 的值使用超过 1 个字节。这unicode/utf8 https://golang.org/pkg/unicode/utf8/包中包含UTF-8相关的实用函数和常量,例如utf8.UTFMax
报告有效 Unicode 代码点在 UTF-8 编码中可以“占用”的最大字节数(为 4)。
这里需要注意一件事:not所有可能的字节序列是validUTF-8 序列。 Astring
may be any字节序列,甚至是无效的 UTF-8 序列。例如string
value "\xff"
表示无效的UTF-8字节序列,详情参见如何在 Go 中表示可选字符串? https://stackoverflow.com/questions/30731687/how-do-i-represent-an-optional-string-in-go/30741287#30741287
The for range https://golang.org/ref/spec#For_statements构造——当应用于string
value——迭代的符文string
:
对于字符串值,“range”子句从字节索引 0 开始迭代字符串中的 Unicode 代码点。在连续迭代中,索引值将是连续 UTF-8 编码代码点的第一个字节的索引字符串和类型的第二个值rune
,将是相应代码点的值。如果迭代遇到无效的 UTF-8 序列,则第二个值将为0xFFFD
,Unicode 替换字符,下一次迭代将在字符串中前进一个字节。
The for range
构造可能会产生 1 或 2 个迭代值。当使用 2 时,如您的示例所示:
for pos, char := range "日本\x80語" {
fmt.Printf("Character %#U, at position: %d\n", char, pos)
}
对于每次迭代,pos
将是符文/字符的字节索引,并且char
将是符文string
。正如您在上面的引用中看到的,如果string
是无效的UTF-8字节序列,当遇到无效的UTF-8序列时,char
将0xFFFD
(Unicode 替换字符),以及for range
构造(迭代)将推进仅单字节.
把它们加起来:位置始终是字节索引rune
当前迭代的(或更具体地说:UTF-8 编码序列的第一个字节的字节索引rune
当前迭代的位置),但如果遇到无效的UTF-8序列,则在下一次迭代中位置(索引)只会增加1。
如果您想了解有关该主题的更多信息,必读博客文章:
Go 博客:Go 中的字符串、字节、符文和字符 https://blog.golang.org/strings