深入理解 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结构体嵌套的切片数组操作
Apr 28 Golang
彻底理解golang中什么是nil
Apr 29 Golang
Golang 获取文件md5校验的方法以及效率对比
May 08 Golang
Golang生成Excel文档的方法步骤
Jun 09 Golang
再次探讨go实现无限 buffer 的 channel方法
Jun 13 Golang
Go语言设计模式之结构型模式
Jun 22 Golang
go select编译期的优化处理逻辑使用场景分析
Jun 28 Golang
详解Go语言Slice作为函数参数的使用
Jul 02 Golang
golang 语言中错误处理机制
Aug 30 Golang
如何解决goland,idea全局搜索快捷键失效问题
Apr 03 Golang
golang语言指针操作
Apr 14 Golang
Go gRPC进阶教程gRPC转换HTTP
Jun 16 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 正则表达式小结
2009/08/31 PHP
PHP学习之数组的定义和填充
2011/04/17 PHP
php微信公众号开发模式详解
2016/11/28 PHP
php+redis实现消息队列功能示例
2019/09/19 PHP
免费空间广告万能消除代码
2006/09/04 Javascript
javascript倒计时功能实现代码
2012/06/07 Javascript
文字不间断滚动(上下左右)实例代码
2013/04/21 Javascript
js正则表达式的使用详解
2013/07/09 Javascript
js控制再次点击按钮之间的间隔时间可防止重复提交
2014/08/01 Javascript
innerHTML动态添加html代码和脚本兼容多个浏览器
2014/10/11 Javascript
node.js中的fs.chown方法使用说明
2014/12/16 Javascript
js光标定位文本框回车表单提交问题的解决方法
2015/05/11 Javascript
drag-and-drop实现图片浏览器预览
2015/08/06 Javascript
使用jQuery或者原生js实现鼠标滚动加载页面新数据
2016/03/06 Javascript
JS实现关闭当前页而不弹出提示框的方法
2016/06/22 Javascript
AngularJs expression详解及简单示例
2016/09/01 Javascript
jQuery实现简易的输入框字数计数功能示例
2017/01/16 Javascript
简单文件操作python 修改文件指定行的方法
2013/05/15 Python
利用Python批量压缩png方法实例(支持过滤个别文件与文件夹)
2017/07/30 Python
django Admin文档生成器使用详解
2019/07/22 Python
Python 日期的转换及计算的具体使用详解
2020/01/16 Python
基于pytorch padding=SAME的解决方式
2020/02/18 Python
django使用F方法更新一个对象多个对象字段的实现
2020/03/28 Python
python关于倒排列的知识点总结
2020/10/13 Python
Agoda.com官方网站:便宜预订全球酒店,高达80%的折扣
2018/04/04 全球购物
英国第一的市场和亚马逊替代品:OnBuy
2019/03/16 全球购物
Gretna Green中文官网:苏格兰格林小镇
2019/10/16 全球购物
澳大利亚厨房和家用电器购物网站:Bing Lee
2021/01/11 全球购物
Oracle里面常用的数据字典有哪些
2014/02/14 面试题
Java面试题:Java类的Main方法如果是Private将会怎么样
2016/08/18 面试题
培训心得体会
2013/12/29 职场文书
幼儿园家长评语
2014/02/10 职场文书
党员民主生活会对照检查材料思想汇报
2014/09/28 职场文书
2014年学校财务工作总结
2014/12/06 职场文书
2014年小学语文工作总结
2014/12/20 职场文书
宿舍管理制度范本
2015/08/07 职场文书