深入理解 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如何替换某个文件中的字符串
Apr 25 Golang
Go语言中的UTF-8实现
Apr 26 Golang
golang中切片copy复制和等号复制的区别介绍
Apr 27 Golang
golang通过递归遍历生成树状结构的操作
Apr 28 Golang
浅谈golang package中init方法的多处定义及运行顺序问题
May 06 Golang
Golang并发操作中常见的读写锁详析
Aug 30 Golang
Golang ort 中的sortInts 方法
Apr 24 Golang
Golang入门之计时器
May 04 Golang
详解Go语言中Get/Post请求测试
Jun 01 Golang
GoFrame基于性能测试得知grpool使用场景
Jun 21 Golang
go goth封装第三方认证库示例详解
Aug 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
探讨:array2xml和xml2array以及xml与array的互相转化
2013/06/24 PHP
php删除数组元素示例分享
2014/02/17 PHP
php中限制ip段访问、禁止ip提交表单的代码分享
2014/08/22 PHP
叫你如何修改Nginx与PHP的文件上传大小限制
2014/09/10 PHP
php打印一个边长为N的实心和空心菱型的方法
2015/03/02 PHP
php将日期格式转换成xx天前的格式
2015/04/16 PHP
PHP的Socket通信之UDP通信实例
2015/07/02 PHP
php将html转成wml的WAP标记语言实例
2015/07/08 PHP
编写PHP脚本来实现WordPress中评论分页的功能
2015/12/10 PHP
使用jQuery内容过滤选择器选择元素实例讲解
2013/04/18 Javascript
jquery实现相册一下滑动两次的方法
2015/02/09 Javascript
javascript单例模式的简单实现方法
2015/07/25 Javascript
jQuery点击其他地方时菜单消失的实现方法
2016/04/22 Javascript
jQuery+CSS3文字跑马灯特效的简单实现
2016/06/25 Javascript
JS实现的tab切换选项卡效果示例
2017/02/28 Javascript
js 显示日期时间的实例(时间过一秒加1)
2017/10/25 Javascript
JavaScript生成简单等差数列
2017/11/28 Javascript
Jquery和CSS实现选择框重置按钮功能
2018/11/08 jQuery
微信小程序开发问题之wx.previewImage
2018/12/25 Javascript
js中对象和面向对象与Json介绍
2019/01/21 Javascript
jquery登录的异步验证操作示例
2019/05/09 jQuery
详解vue 动态加载并注册组件且通过 render动态创建该组件
2019/05/30 Javascript
Vue项目配置跨域访问和代理proxy设置方式
2020/09/08 Javascript
Python urllib模块urlopen()与urlretrieve()详解
2013/11/01 Python
python类的方法属性与方法属性的动态绑定代码详解
2017/12/27 Python
Python cookbook(数据结构与算法)根据字段将记录分组操作示例
2018/03/19 Python
Pandas 合并多个Dataframe(merge,concat)的方法
2018/06/08 Python
GLAMGLOW香港官网:明星出镜前的秘密武器
2017/03/16 全球购物
结婚周年感言
2014/02/24 职场文书
大学生自我鉴定书
2014/03/24 职场文书
大学生就业策划书范文
2014/04/04 职场文书
文明寝室标语
2014/06/13 职场文书
少年雷锋观后感
2015/06/10 职场文书
酒店工程部的岗位职责汇总大全
2019/10/23 职场文书
css3中transform属性实现的4种功能
2021/08/07 HTML / CSS
Python+OpenCV实现在图像上绘制矩形
2022/03/21 Python