当前位置:网站首页>Golang 字符串
Golang 字符串
2022-08-03 12:47:00 【云满笔记】
1. Golang 字符串
1.1. 基础概念
ASCII 是英文"American Standard Code for Information Interchange"的缩写,中文译为美国信息交换标准代码,它是由美国国家标准学会 (ANSI) 制定的单字节字符编码方案,它使用单个字节 (byte) 的二进制数来编码一个字符。
Unicode 编码规范为世界上现存的所有自然语言中的每一个字符,都设定了一个唯一的二进制编码。它以 ASCII 编码集为出发点,并突破了 ASCII 只能对拉丁字母进行编码的限制。Unicode 编码规范通常使用十六进制表示法来表示 Unicode 代码的整数值,并提供了三种不同的编码格式,即:UTF-8、UTF-16 和 UTF-32。
UTF-8 以 8 个比特(一个字节)作为一个编码单元,它是一种可变宽的编码方案,它会用一个或多个字节的二进制数来表示某个字符,最多使用四个字节。对于一个英文字符,它仅用一个字节的二进制数就可以表示,而对于一个中文字符,它需要使用三个字节才能够表示。rune 是 Go 语言特有的一个基本数据类型,它的一个值就代表一个 Unicode 字符,比如’吕’、‘M’。一个 rune 类型的值会由四个字节宽度的空间来存储,它的存储空间总是能够存下一个 UTF-8 编码值。
1.2. 字符串编码
一个 rune 类型的值在底层其实就是一个 UTF-8 编码值,前者是(便于我们人类理解的)外部展现,后者是(便于计算机系统理解的)内在表达,请看下面代码:
func main() {
str := "Go 爱好者"
fmt.Printf("The string: %q\n", str)
fmt.Printf("runes(char): %q\n", []rune(str)) //['G' 'o' '爱' '好' '者']
fmt.Printf("runes(hex): %x\n", []rune(str)) //[47 6f 7231 597d 8005]
fmt.Printf("bytes(hex): [% x]\n", []byte(str)) //[47 6f e7 88 b1 e5 a5 bd e8 80 85]
}
对于第 3 行输出,前面解释的比较清楚,就不赘述。对于第 4 行输出,就是通过 UTF-8 编码,3 个字节的 16 进制展现。第 5 行输出,把每个字符的 UTF-8 编码值都拆成相应的字节序列。
一句话总结一下:一个 string 类型的值在底层就是一个能够表达若干个 UTF-8 编码值的字节序列。
1.3. 遍历字符串
range 遍历:
func main() {
str := "Go 爱好者"
fmt.Printf("range 遍历:\n")
for i, c := range str {
fmt.Printf("%d: %q [% x]\n", i, c, []byte(string(c)))
}
fmt.Printf("for 遍历:\n")
for i := 0; i < len(str); i++ {
fmt.Printf("%d: [%c] [%x]\n", i, str[i], str[i])
}
}
输出如下:
range 遍历:
0: 'G' [47]
1: 'o' [6f]
2: ' ' [20]
3: '爱' [e7 88 b1]
6: '好' [e5 a5 bd]
9: '者' [e8 80 85]
for 遍历:
0: [G] [47]
1: [o] [6f]
2: [ ] [20]
3: [ç] [e7]
4: [ˆ] [88]
5: [±] [b1]
6: [å] [e5]
7: [¥] [a5]
8: [½] [bd]
9: [è] [e8]
10: [€] [80]
11: [
] [85]
由此可以看出,通过 range 方式的遍历,是以 rune 为单位,但是相邻字符的索引值并不一定是连续的;通过 for 方式的遍历,是以 byte 为单位。
1.4. 类型转换
字符串是不能直接修改的,如果需要修改,需要转换为可变类型 ([]rune 和 []bype), 待修改完后再转换回来。但不管如何转换,都需要重新分配内存,并复制数据。
func main() {
str := "hello, world!"
bs := []byte(str) // string 转 byte
str2 := string(bs) // byte 转 string
rs := []rune(str) // string 转 rune
str3 := string(rs) // rune 转 string
}
前面已经讲解 string、rune 和 byte 的区别和联系,这里再理解他们的转换,是不是就轻松很多了呢。
1.5. 总结
Go 语言的代码是由 Unicode 字符组成的,它们都必须由 Unicode 编码规范中的 UTF-8 编码格式进行编码并存储,Unicode 编码规范中的编码格式定义的是:字符与字节序列之间的转换方式。其中的 UTF-8 是一种可变宽的编码方案,它会用一个或多个字节的二进制数来表示某个字符,最多使用四个字节。Go 语言中的一个 string 类型值会由若干个 Unicode 字符组成,每个 Unicode 字符都可以由一个 rune 类型的值来承载。这些字符在底层都会被转换为 UTF-8 编码值,而这些 UTF-8 编码值又会以字节序列的形式表达和存储。因此,一个 string 类型的值在底层就是一个能够表达若干个 UTF-8 编码值的字节序列。对于通过 for range 方式遍历字符串,会先把被遍历的字符串值拆成一个字节序列,然后再试图找出这个字节序列中包含的每一个 UTF-8 编码值,或者说每一个 Unicode 字符。相邻的 Unicode 字符的索引值并不一定是连续的,这取决于前一个 Unicode 字符是否为单字节字符,一旦我们清楚了这些内在机制就不会再困惑了。对于 Go 语言来说,Unicode 编码规范和 UTF-8 编码格式算是基础之一,我们应该了解到它们对 Go 语言的重要性,这对于正确理解 Go 语言中的相关数据类型以及日后的相关程序编写都会很有好处。
边栏推荐
- Classes and objects (upper)
- 云计算服务主要安全风险及应对措施初探
- 使用工作队列管理器(三)
- The new interface, jingdong comment interface
- An动画基础之元件的影片剪辑效果
- 【必读要点】Pod控制器Deployment更新、回退详解
- An工具介绍之3D工具
- PolarFormer: Multi-camera 3D Object Detection with Polar Transformers 论文笔记
- How to disable software from running in the background in Windows 11?How to prevent apps from running in the background in Windows 11
- leetcode16 Sum of the closest three numbers (sort + double pointer)
猜你喜欢

(through page) ali time to upload the jar

How can I get a city's year-round weather data for free?Precipitation, temperature, humidity, solar radiation, etc.

leetcode 11. 盛最多水的容器

有趣的opencv-记录图片二值化和相似度实现

leetcode 11. The container that holds the most water

什么是分布式锁?几种分布式锁分别是怎么实现的?

欧曼自动挡、银河大马力、行星新产品 欧曼全新产品以燎原之势赢领市场

An动画基础之元件的影片剪辑动画与传统补间

An动画基础之元件的影片剪辑效果

shell编程之条件语句
随机推荐
PyTorch构建神经网络预测气温(数据集对比,CPU与GPU对比)
【深度学习】高效轻量级语义分割综述
An动画优化之传统引导层动画
秋招招工作
【必读要点】Pod控制器Deployment更新、回退详解
Database basics one (MySQL) [easy to understand]
An动画优化之遮罩层动画
GameFi industry down but not out | June Report
Sogou news - dataset
An工具介绍之钢笔工具、铅笔工具与画笔工具
Golang 接口 interface
Mysql重启后innodb和myisam插入的主键id变化总结
Grafana 高可用部署最佳实践
An animation optimization of traditional guide layer animation
免费的网络传真平台_发传真不显示发送号码
一些测试相关知识
Classes and objects (upper)
Oracle安装完毕(系统盘),从系统盘转移到数据盘
AMS simulation
查看GCC版本_qt版本