您的位置 首页 golang

「Golang系列」 深入理解Golang中得String类型

与JavaScript不同, 字符串 双引号 “…”之间定义,而不是单引号。 Go中的字符串默认为UTF-8 编码 。由于UTF-8支持 ASCII字符集 ,因此在大多数情况下您无需担心编码问题。但要了解UTF-8编码的工作原理,你可以具体查询。

我们来写一个简单的程序。要定义字符串类型的空变量,请使用string关键字。

要查找字符串的长度,可以使用len函数。 len函数在Go运行时可用,因此您无需从任何包中导入它。

这将打印 11 到控制台,因为字符串 s 有11个字符,包括一个空格也是一个字符。字符串 Hello World 中的所有字符都是有效的ASCII字符,因此我们希望看到每个字符只占用内存中的一个字节(因为UTF-8中的ASCII字符占用8位或1字节)。让我们看看在字符串上使用 for循环

其中i是从0开始的字符串中的字符的索引。我猜你可能认为 s[i] 输出结果应该是s 字符串中得字母,那这又是什么呢?嗯,这些是Hello World字符串中ASCII / UTF-8字符的十进制值(参见表)。

在Go中,字符串实际上是只读字节的切片 。现在,想象 切片 就像一个简单的 数组 ,我们将在其他课程中具体学习切片。因此,在上面的例子中,我们看到字符串s的字节( uint8 )值在内部是一个切片。因此 s [i] 打印字符所占有的字节的十进制值。但是要查看单个字符,可以在Printf语句中使用%c格式化字符串。您还可以使用%v格式化字符串来查看字节值和%T以查看值的数据类型。

所以你可以看到每个字母都显示十进制数,它以uint8类型占有8位或1字节的内存。

我们知道,UTF-8字符可以在内存中定义从1个字节(ASCII兼容)到4个字节大小。因此在Go中,所有字符都以int32(4字节大小)数据类型表示。代码单元是编码用于单个单元的位数。因此UTF-8使用8位,UTF-16使用16位,这意味着UTF-8需要最少8位或1字节来表示字符。

代码点是定义字符的任何数值,并且由一个或多个代码单元表示,具体取决于编码。由于UTF-8与ASCII兼容,因此所有ASCII字符都以单字节(8位)表示,因此UTF-8只需要1个代码单元来表示它们。

但最大的问题是,如果UTF-8中的所有字符都用int32表示,那么为什么我们在上面的例子中得到了uint8类型。如前所述,在Go中,字符串是只读字节的切片。当我们对字符串使用len函数时,它会计算该切片的长度。当我们使用for循环时,它会对切片循环,一次返回一个字节或一次返回一个代码单元。到目前为止,我们所有的字符都是ASCII字符集,for循环提供的字节是有效字符,或者代码单元实际上是代码点。因此,Printf语句中的%c可以从该字节值打印有效的字符。但是正如我们所知,UTF-8代码点或字符值可以用一个或多个字节(最多4个字节)的序列表示,如果我们引入非ASCII字符,我们之前看到的for循环会发生什么?

让我们用õ替换Hello 中得 o(带有TILDE的LATIN SMALL LETTER O,http://www.utf8-chartable.de),它具有 Unicode 代码点表示为U+00F5,它由2个代码单元(2个字节)c3 b5 (十六进制表示)表示。因此,我们知道应该用c3 b5表示字符õ,而不是表示字符o得6f。

从上面的结果来看,我们得到的是c3 b5而不是6f,但是HellõWorld的字符并没有很好地打印出来。我们还看到len(s)返回12,因为len计算字符串中的字节数并导致此问题。索引字符串(使用for循环)访问单个字节,而不是字符。因此,UTF-8中的c3(十进制195)表示Ã,而b5(十进制181)表示μ。

为了避免上述混乱,Go引入了数据类型rune,它是int32的别名,Go表示int32数据类型中的字符(代码点)。

为什么rune是int32而不是uint32(因为字符代码点值不能为负,int32数据类型可以包含负值和正值)()。

因此,我们需要将一个字符串转换为runes 的切片,而不bytes 的切片。

我们使用类型转换将字符串转换为runes切片。在上面的结果中看到结果是f5而不是c3 b5,因为我们正在迭代runes数据类型,并且UTF-8表中的代码点是f5(因此是unicode代码点表示U + 00F5)或十进制245。此外,我们得到字符串s的长度11,因为切片中有11个runes(或11个代码点或11个字符)。我们还证明了Go中的代码点或字符由int32数据类型表示。

字符串中的for 循环

如果你再for 循环中使用 range,range 会返回 字符的rune 和 字节索引。

上面的代码中,我们没看到index 5 因为第五个字节是õ 字符的第二个代码单元。如果你不需要索引值, 你可以用_ 来忽略它。

rune 是什么

字符串是字节的切片,就这么简单。当我们使用带有 range 的循环时,我们得到 rune ,因为字符串中的每个字符都由 rune 数据类型表示。在Go中,字符串再单引号间表示。因此,任何有效UTF-8字符在单引号(’)中的都是rune并且它的类型是int32。

上面的代码将在UTF-8表中打印f5 245 int32,它在UTF-8表中是十六进制/十进制值和õ的代码点值的数据类型。

字符串是不可变的

从早期的字符串定义可以看出,它们是只读字节的切片。因此,如果我们尝试替换切片中的任何字节,编译器将抛出错误。

上面的代码不会被编译,编译器会抛出一个错误,意思是不能分配给s [0],因为字符串s是一个只读的字节切片。

使用反引号的字符串

除了双引号,我们也可以使用反引号(`)来表示Go中的字符串。在引号(“)中,您需要转义换行符,制表符和其他不需要在反引号中转义的字符。如果在反引号字符串中添加换行符,则会将其解释为’\ n’字符。

原始字符串文字的值是由反引号之间的未解释(隐式UTF-8编码)字符组成的字符串;特别是,反斜杠没有特殊含义,字符串可能包含换行符。原始字符串文字中的回车符(\ r)将从原始字符串值中丢弃。

我们看个小例子

我们可以看到带有换行符,换行符和双引号的字符串的原始格式保留在输出中。

字符串比较

在Go中用单引号表示的字符是rune并且rune是可以比较,因为它们代表Unicode代码点(int32值)。因此,如果一个字符的十进制值更大,它将大于具有更小十进制的字符。

让我们看一个非常简单的例子。

由于b的int32值大于a,表达式’b’>’a’将为真。让我们看另一个例子。

既然我们知道字符只是内部的int32,我们可以用它们进行各种比较。例如,两个字符值范围之间的for循环。

这是深入理解Go 中字符串 的基本介绍,但是字符串包提供了许多实用功能,可用于对字符串进行各种操作,如 连接,替换,搜索 等。字符串包是Go标准库的一部分。

文章来源:智云一二三科技

文章标题:「Golang系列」 深入理解Golang中得String类型

文章地址:https://www.zhihuclub.com/86267.shtml

关于作者: 智云科技

热门文章

网站地图