深入理解 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项目中使用init()
Apr 12 Golang
go:垃圾回收GC触发条件详解
Apr 24 Golang
go语言求任意类型切片的长度操作
Apr 26 Golang
解决Golang中ResponseWriter的一个坑
Apr 27 Golang
goland 设置project gopath的操作
May 06 Golang
Golang二维数组的使用方式
May 28 Golang
Golang生成Excel文档的方法步骤
Jun 09 Golang
go goroutine 怎样进行错误处理
Jul 16 Golang
基于Go语言构建RESTful API服务
Jul 25 Golang
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 Golang
Golang入门之计时器
May 04 Golang
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
Jun 14 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
PHP实现图片压缩的两则实例
2014/07/19 PHP
PHP中设置一个严格30分钟过期Session面试题的4种答案
2014/07/30 PHP
mysqli扩展无法在PHP7下升级问题的解决
2019/09/10 PHP
Laravel5.1 框架数据库操作DB运行原生SQL的方法分析
2020/01/07 PHP
JQuery 文本框回车跳到下一个文本框示例代码
2013/08/30 Javascript
javascript获取checkbox复选框获取选中的选项
2014/08/12 Javascript
Jquery实现瀑布流布局(备有详细注释)
2015/07/31 Javascript
基于Jquery代码实现支持PC端手机端幻灯片代码
2015/11/17 Javascript
理解javascript中Map代替循环
2016/02/26 Javascript
jQuery简单实现仿京东分类导航层效果
2016/06/07 Javascript
基于jPlayer三分屏的制作方法
2016/12/21 Javascript
微信小程序网络请求wx.request详解及实例
2017/05/18 Javascript
webstorm中配置nodejs环境及npm的实例
2018/05/15 NodeJs
Vuex 快速入门(简单易懂)
2018/09/20 Javascript
JavaScript事件对象深入详解
2018/12/30 Javascript
利用angular自动编译andriod APK的绕坑经历分享
2019/03/08 Javascript
node学习笔记之读写文件与开启第一个web服务器操作示例
2019/05/29 Javascript
解决echarts中横坐标值显示不全(自动隐藏)问题
2020/07/20 Javascript
python获得两个数组交集、并集、差集的方法
2015/03/27 Python
Python实现豆瓣图片下载的方法
2015/05/25 Python
Python pickle模块用法实例分析
2015/05/27 Python
Python实现删除列表中满足一定条件的元素示例
2017/06/12 Python
Python探索之ModelForm代码详解
2017/10/26 Python
VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法详解
2019/07/01 Python
python中 * 的用法详解
2019/07/10 Python
python实现倒计时小工具
2019/07/29 Python
Python 类的魔法属性用法实例分析
2019/11/21 Python
python 控制台单行刷新,多行刷新实例
2020/02/19 Python
python 判断txt每行内容中是否包含子串并重新写入保存的实例
2020/03/12 Python
基于opencv实现简单画板功能
2020/08/02 Python
python实现录制全屏和选择区域录屏功能
2021/02/05 Python
英国最大的户外商店:Go Outdoors
2019/04/17 全球购物
兼职学生的自我评价
2013/11/24 职场文书
城管年度个人总结
2015/02/28 职场文书
2015年医院创卫工作总结
2015/04/22 职场文书
2015中秋节晚会主持词
2015/07/01 职场文书