「GCTT 出品」Go 系列教程14. 字符串

Go语言中文网,致力于每日分享编码知识,欢迎关注我,会有意想不到的收获!

Go 系列教程是非常棒的一套初学者教程,入门就它了。

「GCTT 出品」Go 系列教程1. 介绍与安装

「GCTT 出品」Go 系列教程2. Hello World

「GCTT 出品」Go 系列教程3. 变量

「GCTT 出品」Go 系列教程4. 类型

「GCTT 出品」Go 系列教程5. 常量

「GCTT 出品」Go 系列教程6. 函数(Function)

「GCTT 出品」Go 系列教程7. 包

Go 系列教程8. if-else 语句

「GCTT 出品」Go 系列教程9. 循环

「GCTT 出品」Go 系列教程10. switch 语句

「GCTT 出品」Go 系列教程11. 数组和切片

「GCTT 出品」Go 系列教程12. 可变参数函数

「GCTT 出品」Go 系列教程13. Maps

这是 Golang 系列教程中的第 14 篇。在本章教程中,我们将讨论 Go 语言中字符串。

由于和其他语言相比,字符串在 Go 语言中有着自己特殊的实现,因此在这里需要被特别提出来。

01 什么是字符串?

Go 语言中的字符串是一个字节切片。把内容放在双引号""之间,我们可以创建一个字符串。让我们来看一个创建并打印字符串的简单示例。

上面的程序将会输出 Hello World。

Go 中的字符串是兼容 Unicode 编码的,并且使用 UTF-8 进行编码。

02 单独获取字符串的每一个字节

由于字符串是一个字节切片,所以我们可以获取字符串的每一个字节。

上面程序的第 8 行,len(s) 返回字符串中字节的数量,然后我们用了一个 for 循环以 16 进制的形式打印这些字节。%x 格式限定符用于指定 16 进制编码。上面的程序输出 48 65 6c 6c 6f 20 57 6f 72 6c 64。这些打印出来的字符是 "Hello World" 以 Unicode UTF-8 编码的结果。为了更好的理解 go 中的字符串,需要对 Unicode 和 UTF-8 有基础的理解。我推荐阅读一下 https://naveenr.net/unicode-character-set-and-utf-8-utf-16-utf-32-encoding/ 来理解一下什么是 Unicode 和 UTF-8。

让我们稍微修改一下上面的程序,让它打印字符串的每一个字符。

在 printChars 方法(第 16 行中)中,%c 格式限定符用于打印字符串的字符。这个程序输出结果是:

48 65 6c 6c 6f 20 57 6f 72 6c 64 
H e l l o W o r l d

上面的程序获取字符串的每一个字符,虽然看起来是合法的,但却有一个严重的 bug。让我拆解这个代码来看看我们做错了什么。

上面代码输出的结果是:

48 65 6c 6c 6f 20 57 6f 72 6c 64 
H e l l o W o r l d 
53 65 c3 b1 6f 72 
S e à ± o r

在上面程序的第 28 行,我们尝试输出 Señor 的字符,但却输出了错误的 S e à ± o r。 为什么程序分割 Hello World 时表现完美,但分割 Señor 就出现了错误呢?这是因为 ñ 的 Unicode 代码点(Code Point)是 U+00F1。它的 UTF-8 编码占用了 c3 和 b1 两个字节。它的 UTF-8 编码占用了两个字节 c3 和 b1。而我们打印字符时,却假定每个字符的编码只会占用一个字节,这是错误的。在 UTF-8 编码中,一个代码点可能会占用超过一个字节的空间。那么我们该怎么办呢?rune 能帮我们解决这个难题。

03 rune

rune 是 Go 语言的内建类型,它也是 int32 的别称。在 Go 语言中,rune 表示一个代码点。代码点无论占用多少个字节,都可以用一个 rune 来表示。让我们修改一下上面的程序,用 rune 来打印字符。

在上面代码的第 14 行,字符串被转化为一个 rune 切片。然后我们循环打印字符。程序的输出结果是

48 65 6c 6c 6f 20 57 6f 72 6c 64 
H e l l o W o r l d 
53 65 c3 b1 6f 72 
S e ñ o r

上面的输出结果非常完美,就是我们想要的结果:)。

04 字符串的 for range 循环

上面的程序是一种遍历字符串的好方法,但是 Go 给我们提供了一种更简单的方法来做到这一点:使用 for range 循环。

在上面程序中的第8行,使用 for range 循环遍历了字符串。循环返回的是是当前 rune 的字节位置。程序的输出结果为:

S starts at byte 0 
e starts at byte 1 
ñ starts at byte 2
o starts at byte 4 
r starts at byte 5

从上面的输出中可以清晰的看到 ñ 占了两个字节:)。

05 用字节切片构造字符串

上面的程序中 byteSlice 包含字符串 Café 用 UTF-8 编码后的 16 进制字节。程序输出结果是 Café。

如果我们把 16 进制换成对应的 10 进制值会怎么样呢?上面的程序还能工作吗?让我们来试一试:

上面程序的输出结果也是Café

06 用 rune 切片构造字符串

在上面的程序中 runeSlice 包含字符串 Señor的 16 进制的 Unicode 代码点。这个程序将会输出Señor。

07 字符串的长度

utf8 package 包中的 func RuneCountInString(s string) (n int) 方法用来获取字符串的长度。这个方法传入一个字符串参数然后返回字符串中的 rune 的数量。

上面程序的输出结果是:

length of Señor is 5 
length of Pets is 4

08 字符串是不可变的

Go 中的字符串是不可变的。一旦一个字符串被创建,那么它将无法被修改。

在上面程序中的第 8 行,我们试图把这个字符串中的第一个字符修改为 'a'。由于字符串是不可变的,因此这个操作是非法的。所以程序抛出了一个错误 main.go:8: cannot assign to s[0]。

为了修改字符串,可以把字符串转化为一个 rune 切片。然后这个切片可以进行任何想要的改变,然后再转化为一个字符串。

在上面程序的第 7 行,mutate 函数接收一个 rune 切片参数,它将切片的第一个元素修改为 'a',然后将 rune 切片转化为字符串,并返回该字符串。程序的第 13 行调用了该函数。我们把 h 转化为一个 rune 切片,并传递给了 mutate。这个程序输出 aello。

我已经在 github 上创建了一个程序,里面包含所有我们讨论过的内容。你可以在这下载https://github.com/golangbot/stringsexplained 它。

关于字符串的介绍到此为止。祝你愉快。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

热门产品

php编程基础教程.pptx|php编程培训,php,编程,基础,教程,pptx
php编程基础教程.pptx

历史上的今天:04月29日

热门专题

安徽开放大学|安徽开放大学报名,安徽开放大学报考,安徽开放大学,什么是安徽开放大学,安徽开放大学学历,安徽开放大学学费,安徽开放大学报名条件,安徽开放大学报名时间,安徽开放大学学历,安徽开放大学专业
安徽开放大学
开放大学|开放大学报名,开放大学报考,开放大学,什么是开放大学,开放大学学历,开放大学学费,开放大学报名条件,开放大学报名时间,开放大学学历,开放大学专业
开放大学
安徽中源管业|安徽中源管业,安徽中源管业mpp电力管,安徽中源管业cpvc电力管,安徽中源管业pe穿线管,安徽中源管业电力管,安徽中源管业排水管,安徽中源管业通信管,安徽中源管业管材
安徽中源管业
外贸网站建设|外贸网站建设,英文网站制作,英文网站设计,美国主机空间,外贸建站平台,多语言网站制作
外贸网站建设
昆明网站建设|昆明网站建设,昆明网站开发,昆明网站建设公司,昆明网站建设价格,昆明网站设计,昆明网站制作,网页设计,高端网站建设,高端网站设计
昆明网站建设
易捷尔高职单招|易捷尔高职单招,易捷尔高职单招培训,单招分数线,单招录取分数线,高职单招学校分数线
易捷尔高职单招
易捷尔单招|易捷尔单招,易捷尔单招培训,易捷尔单招报名,易捷尔单招考试,易捷尔单招培训学校,易捷尔单招分数
易捷尔单招
一年制中专|中专学历,中专是什么学历,中专是什么,中专有什么专业,中专升大专,一年制中专
一年制中专

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部