深入理解 Golang 的字符串


Posted in Golang onMay 04, 2022

字符串的本质

在编程语言中,字符串发挥着重要的角色。字符串背后的数据结构一般有两种类型:

  • 一种在编译时指定长度,不能修改
  • 一种具有动态的长度,可以修改。

比如:与Python 中的字符串一样,Go 语言中的字符串不能被修改,只能被访问。
在 Python 中,如果改变一个字符串的值会得到如下结果:

>>> hi = "Hello"
>>> hi
'Hello'
>>> hi[0] = 'h'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>>

同理,在 Go 中也一样:

package main
import "fmt"
func main() {
var hello = "Hello"
hello[1] = 'h'
fmt.Println(hello)
}
// # command-line-arguments
// string_in_go/main.go:8:11: cannot assign to hello[1] (strings are immutable)

字符串的终止方式有两种:

  • 一种是 C 语言的隐式声明,以字符 “\0” 作为终止符
  • 一种是 Go 语言的显式声明

Go 语言的 string 的表示结构如下:

type StringHeader struct {
Data uintptr // Data 指向底层的字符数组
Len int // Len 用来表示字符串的长度
}

字符串的本质上是一串字符数组,每个字符都在存储时对应了一个或多个整数。用这些整数来表示字符,比如打印 hello 的字节数组如下:

package main
import "fmt"
func main() {
var hello = "Hello"
for i := 0; i < len(hello); i++ {
fmt.Printf("%x ", hello[i])
}
}
// Output: 48 65 6c 6c 6f

字符串的底层原理

字符串有特殊标识,有两种声明方式:

var s1 string = `hello world`
var s2 string = "hello world"

字符串常量在词法解析阶段最终会被标记为 StringLit 类型的 Token 并被传递到编译的下一个阶段。
在语法分析阶段,采取递归下降的方式读取 UTF-8 字符,单撇号或双引号是字符串的标识。

分析的逻辑位于  syntax/scanner.go 文件中:

func (s *scanner) stdString() {
ok := true
s.nextch()
for {
if s.ch == '"' {
s.nextch()
break
}
if s.ch == '\\' {
s.nextch()
if !s.escape('"') {
ok = false
}
continue
}
if s.ch == '\n' {
s.errorf("newline in string")
ok = false
break
}
if s.ch < 0 {
s.errorAtf(0, "string not terminated")
ok = false
break
}
s.nextch()
}
s.setLit(StringLit, ok)
}
func (s *scanner) rawString() {
ok := true
s.nextch()
for {
if s.ch == '`' {
s.nextch()
break
}
if s.ch < 0 {
s.errorAtf(0, "string not terminated")
ok = false
break
}
s.nextch()
}
// We leave CRs in the string since they are part of the
// literal (even though they are not part of the literal
// value).
s.setLit(StringLit, ok)
}

从上面的代码可以看到,Go 中有两种字符串的检查:一种是标准字符串以双引号定义 "",如 "Hello,World", 还有一种是原始字符串,用 \\ 定义的, 因此针对两种字符串有两种语法分析函数:

  • 如果是单撇号,则调用 rawString 函数
  • 如果是双引号,则调用 stdString 函数
Golang 相关文章推荐
go语言map与string的相互转换的实现
Apr 07 Golang
go原生库的中bytes.Buffer用法
Apr 25 Golang
解决Golang time.Parse和time.Format的时区问题
Apr 29 Golang
对Golang中的FORM相关字段理解
May 02 Golang
Golang实现AES对称加密的过程详解
May 20 Golang
golang fmt格式“占位符”的实例用法详解
Jul 04 Golang
go goroutine 怎样进行错误处理
Jul 16 Golang
golang实现一个简单的websocket聊天室功能
Oct 05 Golang
Golang中channel的原理解读(推荐)
Oct 16 Golang
golang生成vcf通讯录格式文件详情
Mar 25 Golang
Go 中的空白标识符下划线
Mar 25 Golang
Golang实现可重入锁的示例代码
May 25 Golang
Golang入门之计时器
May 04 #Golang
Golang 入门 之url 包
May 04 #Golang
Golang解析JSON对象
Apr 30 #Golang
Golang 并发编程 SingleFlight模式
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 #Golang
Golang 实现WebSockets
Golang ort 中的sortInts 方法
Apr 24 #Golang
You might like
mysql中存储过程、函数的一些问题
2007/02/14 PHP
PHP5中的this,self和parent关键字详解教程
2007/03/19 PHP
PHP中ADODB类详解
2008/03/25 PHP
Zend Studio 实用快捷键一览表(精心整理)
2013/08/10 PHP
PHP不使用递归的无限级分类简单实例
2016/11/05 PHP
Yii2语言国际化的配置教程
2018/08/19 PHP
PHP使用 Pear 进行安装和卸载包的方法详解
2019/07/08 PHP
用javascript实现无刷新更新数据的详细步骤 asp
2006/12/26 Javascript
简单的无缝滚动程序-仅几行代码
2007/05/08 Javascript
编写高效jQuery代码的4个原则和5个技巧
2014/04/24 Javascript
jQuery制作简洁的多级联动Select下拉框
2014/12/23 Javascript
JavaScript语言精粹经典实例(整理篇)
2016/06/07 Javascript
JS解惑之Object中的key是有序的么
2019/05/06 Javascript
[25:45]2018DOTA2亚洲邀请赛4.5SOLO赛 Sylar vs Paparazi
2018/04/06 DOTA
详解Python中for循环的使用方法
2015/05/14 Python
利用numpy+matplotlib绘图的基本操作教程
2017/05/03 Python
Python实现字典去除重复的方法示例
2017/07/31 Python
python通过socket实现多个连接并实现ssh功能详解
2017/11/08 Python
Python3中bytes类型转换为str类型
2018/09/27 Python
Python中fnmatch模块的使用详情
2018/11/30 Python
pytorch 获取tensor维度信息示例
2020/01/03 Python
利用Python计算KS的实例详解
2020/03/03 Python
使用python 计算百分位数实现数据分箱代码
2020/03/03 Python
简单了解django处理跨域请求最佳解决方案
2020/03/25 Python
Django数据统计功能count()的使用
2020/11/30 Python
深入解读CSS3中transform变换模型的渲染
2016/05/27 HTML / CSS
2013年入党人员的自我鉴定
2013/10/25 职场文书
大学生职业生涯规划书范文
2014/01/14 职场文书
校庆接待方案
2014/03/18 职场文书
校庆标语集锦
2014/06/25 职场文书
诉讼授权委托书
2014/10/15 职场文书
2014年转正工作总结
2014/11/08 职场文书
2015年七夕情人节活动方案
2015/05/06 职场文书
周一问候语大全
2015/11/10 职场文书
CSS的class与id常用的命名规则
2021/05/18 HTML / CSS
Python学习之迭代器详解
2022/04/01 Python