golang for循环_「Golang系列」 深入理解Golang中得String类型

1a147ca9f127104fad0a526be1863ebc.png

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

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

08403d0bfffade373c336966ba2462d8.png

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

len是一个查找任何数据类型长度的通用函数,它并不特定于字符串。我们将在即将到来的教程中学习更多Go的内置函数。

93a6bbe5ee47418734a04bcca64a28b6.png

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

cfba758c9a2be41f9a36e6f57e41f85e.png

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

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

45d73fbedb07e8bcb75cdd47f6e813f8.png

所以你可以看到每个字母都显示十进制数,它以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。

ec707c7b4f1e0514206d23b8dea4518e.png

从上面的结果来看,我们得到的是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数据类型可以包含负值和正值)(https://stackoverflow.com/questions/24714665/why-is-rune-in-golang-an-alias-for-int32-and-not-uint32)。

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

1470b31f4082bb9c0b2f17be18dd74d5.png

我们使用类型转换将字符串转换为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 和 字节索引。

901c0de31448faf7167f919a5a94cf41.png

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

rune 是什么

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

e7fcbd74f9675fbdfb6fcc657d3ea1e9.png

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

字符串是不可变的

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

51d4bc5accc77416142ab57d68ebfa78.png

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

使用反引号的字符串

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

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

我们看个小例子

a0b4ebefbe21c1f42a1248252fa72e7e.png

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

字符串比较

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

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

ceb967431c515363259fa0cd128bde71.png

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

c872098eadf3bf7aa22f858b6a56dcd5.png

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

f695e93bd2a28607ad296e74c9cfd6ae.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值