深入理解 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 相关文章推荐
golang interface判断为空nil的实现代码
Apr 24 Golang
win10下go mod配置方式
Apr 25 Golang
golang 如何通过反射创建新对象
Apr 28 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
Go 实现英尺和米的简单单位换算方式
Apr 29 Golang
解决golang在import自己的包报错的问题
Apr 29 Golang
Go语言 go程释放操作(退出/销毁)
Apr 30 Golang
完美解决golang go get私有仓库的问题
May 05 Golang
golang中的并发和并行
May 08 Golang
基于Go语言构建RESTful API服务
Jul 25 Golang
Go语言基础切片的创建及初始化示例详解
Nov 17 Golang
Go语言编译原理之变量捕获
Aug 05 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
对text数据类型不支持代码页转换 从: 1252 到: 936
2011/04/23 PHP
PHP文件上传原理简单分析
2011/05/29 PHP
js类中获取外部函数名的方法
2007/08/19 Javascript
jQuery的实现原理的模拟代码 -1 核心部分
2010/08/01 Javascript
Javascript玩转继承(一)
2014/05/08 Javascript
Node.js的包详细介绍
2015/01/14 Javascript
jquery中EasyUI实现异步树
2015/03/01 Javascript
JavaScript实现多个重叠层点击切换效果的方法
2015/04/24 Javascript
JS实现无限级网页折叠菜单(类似树形菜单)效果代码
2015/09/17 Javascript
Bootstrap路径导航与分页学习使用
2017/02/08 Javascript
实例解析js中try、catch、finally的执行规则
2017/02/24 Javascript
jQuery EasyUI开发技巧总结
2017/09/26 jQuery
webpack多入口文件页面打包配置详解
2018/01/09 Javascript
JavaScript同源策略和跨域访问实例详解
2018/04/03 Javascript
基于Vue自定义指令实现按钮级权限控制思路详解
2018/05/23 Javascript
微信小程序实现搜索功能并跳转搜索结果页面
2019/05/18 Javascript
JS猜数字游戏实例讲解
2020/06/30 Javascript
Python中apply函数的用法实例教程
2014/07/31 Python
理解Python中函数的参数
2015/04/27 Python
Python脚本实现Web漏洞扫描工具
2016/10/25 Python
python3中zip()函数使用详解
2018/06/29 Python
使用python Fabric动态修改远程机器hosts的方法
2018/10/26 Python
python 使用re.search()筛选后 选取部分结果的方法
2018/11/28 Python
使用python3调用wxpy模块监控linux日志并定时发送消息给群组或好友
2019/06/05 Python
python的命名规则知识点总结
2019/10/04 Python
python的range和linspace使用详解
2019/11/27 Python
如何用Python绘制3D柱形图
2020/09/16 Python
使用OpenCV校准鱼眼镜头的方法
2020/11/26 Python
英国最大的邮寄种子和植物公司:Thompson & Morgan
2017/09/21 全球购物
Audible英国:有声读物,30天免费试用
2019/10/16 全球购物
Exception类的常用方法
2012/06/16 面试题
客户表扬信范文
2014/01/10 职场文书
经验丰富大学生村干部自我鉴定
2014/01/22 职场文书
财会专业大学生求职信
2014/09/26 职场文书
交通事故一次性赔偿协议书范本
2014/11/02 职场文书
CSS 左边固定宽右边自适应的6种方法
2022/05/15 HTML / CSS