Go语言设计与实现 -- 字符串

news2025/1/20 2:02:19

Go语言的字符串与Java和python是一样的。具有不可变性。是一个只读的字节数组,如图所示。

请添加图片描述

因为Go的字符串具有不可变性,所以我们只能通过string[]byte类型之间反复转换实现修改。

  • 将这一段内存复制到栈上
  • 将变量的类型转换成[]byte后并修改字节数据
  • 将修改后的字节数组转换回string

字符串的数据结构与切片的数据结构

首先来看一下字符串的数据结构:

type StringHeader struct {
    Data uintptr
    Len  int
}

然后我们再来看一下切片的数据结构:

type SliceHeader struct {
    Data   uintptr
    Len    int 
    Cap    int
}

可以看到和字符串相比,切片的数据结构仅仅多了一个Cap而已。

所以我们说:字符串是只读的切片类型

字符串解析过程

在了解字符串解析过程之前,我们先来了解一下编译的大致流程

  • 词法分析 – 解析源代码文件,把文件中的字符串序列转换成Token序列。这个字符串不包含空格,换行等字符。我们把执行词法分析的程序叫做词法分析器
  • 语法分析 – 词法分析的输出的Token序列就是语法分析的输入。它可以把Token序列转换成有意义的结构体,即语法树
  • 类型检查 – 检查语法树中的定义和使用的类型,所有类型错误和不匹配都会在这个阶段暴露出来
  • 中间代码生成 – 类型检查过后,编译器就不存在语法错误和类型不匹配的问题了,这个时候gc.compileFunctions会编译整个Go语言项目中的全部函数,在一个编译队列里面等待几个Goroutine消费,并发执行Goroutine会将所有函数对应的抽象语法树转换成中间代码。在这个过程中,代码已经做好了优化,例如SSA静态单赋值的优化
  • 机器码生成

接下来回到字符串的解析过程。

词法分析器会在词法阶段解析字符串,该阶段会把无意义的字符串流转换成Token字符串。

我们有两种方式来声明一个字符串

// 双引号
str1 := "this is a string"
// 单引号
str2 := `this is another
string`

当我们使用双引号的时候,如果字符串内部有""的话,那么我们需要加上\符号来避免编译器的解析错误。所以当我们要手写json字符串的时候,我们最好使用单引号。

双引号字符串解析

先来看一下源码。

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)
}

可以看到是把非反引号的所有字符都划分到当前字符串的范围中。

我们看到代码可以发现这两种转换方式都有一个共同特点:

s.setLit(StringLit, ok)

我们都会被标记为StringLit并传递到语法分析阶段。然后执行basicLit这个函数。

这个函数可以去掉字符串两边的引号等无关干扰,还原其本来面目

字符串拼接

Go语言的字符串使用+来进行拼接。

Go会自动的判断要拼接的字符串的数量

  • 如果数量少于或者等于5个,那么会调用concatstring{2, 3, 4, 5}等一系列函数
  • 如果超过5个,那么会选择runtime.Concatstrings传入一个数组切片

但是不管使用concatstring{2, 3, 4, 5}中的哪一个,最终都会调用runtime.concatstrings

这个函数会过滤空字符串并计算拼接后字符串的长度。

如果非空字符串的数量为1,并且当前字符串不在栈上,就直接返回这个字符串,不需要格外操作。

否则拼接的字符串是一块新的内存空间,与原来的字符串没有任何关联。

类型转换

string-bytes-conversion

图片来自于面向信仰编程

字符串和 []byte 中的内容虽然一样,但是字符串的内容是只读的,我们不能通过下标或者其他形式改变其中的数据,而 []byte 中的内容是可以读写的。不过无论从哪种类型转换到另一种都需要拷贝数据,而内存拷贝的性能损耗会随着字符串和 []byte 长度的增长而增长。

总结:由于这些都是拷贝的操作,所以我们要注意性能问题!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/106096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

功能上新|使用 Excel 低门槛进行指标分析!

Kyligence Zen 功能上新啦&#xff01;用户不仅可以在 Kyligence Zen 中定义、分析和管理指标&#xff0c;还可直接使用 Excel 插件来分析 Kyligence Zen 中已经定义好的指标&#xff0c;学习无门槛&#xff0c;上手更轻松&#xff01;欢迎访问 http://zen.kyligence.io 申请免…

实验二A 图像的空域(源代码一站式复制粘贴)

实验二A 图像的空域一、实验目的二、实验原理三、实验内容与要求四、实验的具体实现一、实验目的 1.掌握图像滤波的基本定义及目的。 2.理解空间域滤波的基本原理及方法。 3.掌握进行图像的空域滤波的方法。 二、实验原理 1.空域增强 空域滤波是在图像空间中借助模板对图像进…

阳哥JUC并发编程之AQS后篇全网最详细源码笔记

文章目录AQS后序课程笔记AQS源码ReentryLock锁的原理分析公平锁以及非公平锁源码详解Aquire方法调用原码流程分析第一步、tryAquire第二步、addwrite第三步&#xff1a;aquireQueuedAQS释放锁的过程第一步、释放锁第二步进入aquireQueueAQS异常情况下走Cancel流程分析第一种队尾…

ECharts项目实战:全球GDP数据可视化

【课程简介】 可视化是前端里一个几乎可以不用写网页&#xff0c;但又发展得非常好的方向。在互联网产品里&#xff0c;无论是C端中常见的双十一购物节可视化大屏&#xff0c;还是B端的企业中后台管理系统都离不开可视化。国家大力推动的智慧城市、智慧社区中也有很多可视化的…

对于DDoS攻击防御有哪些误区?

​  DDoS攻击是属于常见网络攻击之一&#xff0c;也是一种较难防御的网络攻击。它的特点就是易于启动、难防御、有害、难跟踪等。因此DDoS攻击也是众多站长最怕遇见的网络攻击。那么大家在使用海外服务器时&#xff0c;会有哪些DDoS攻击防御的误区呢? 1、防御全部DDoS攻击 防…

CSS -- 09. 移动WEB开发之flex布局

文章目录移动WEB开发之flex布局1 flex布局原理2 常见的父项属性2.1 设置主轴方向 flex-direction2.2 设置主轴上的子元素排列方式 justify-content2.3 设置元素是否换行 flex-wrap2.4 设置侧轴上的子元素的排列方式&#xff08;单行&#xff09; align-items2.5 设置侧轴上的子…

【矩阵论】6.范数理论——基本概念——矩阵范数生成向量范数谱范不等式

6.1.3 矩阵范数产生向量范数 CnnC^{n\times n}Cnn 上任一矩阵范数 ∥∙∥\Vert \bullet\Vert∥∙∥ 都产生一个向量范数 φ(X)∥X∥V\varphi(X)\Vert X\Vert_Vφ(X)∥X∥V​ 矩阵范数与向量范数的相容性&#xff1a;φ(Ax)≤∥A∥φ(x)\varphi(Ax)\le \Vert A\Vert\varphi(x)φ…

MySQL SSL安全解读

安全一直是不可不重视的问题。目前MySQL这方面应大方向上技术手段都具备。如&#xff1a;网络链接&#xff0c;权限控制&#xff0c;key秘钥认证&#xff0c;数据加密脱敏 等方式。综合考虑&#xff0c;虽然很多环境无法所有这些安全策略全部应用上&#xff0c;但在可控范围内尽…

【C语言数据结构(基础版)】第五站:树和二叉树

目录 一、树的概念及结构 1.树的概念 2.树的表示 3.树在实际中的应用 二、二叉树概念及结构 1.概念 2.特殊的二叉树 3.二叉树的性质 4.二叉树的存储结构 &#xff08;1&#xff09;顺序存储 &#xff08;2&#xff09;链式存储 三、二叉树链式结构的实现 1.二叉树的…

Mysql的MVCC知多少(隐藏字段,undolog版本链和ReadView)

文章目录前言一、什么是MVCC二、快照读与当前读三、4种隔离级别与MVCC四、MVCC实现4.1 隐藏字段和undolog版本链4.2 ReadView五、说明前言 其实自己之前对MVCC知之甚少&#xff0c;总觉得是一块很难啃的骨头&#xff0c;有点内惧&#xff0c;但当你真的掌握之后&#xff0c;就…

Fastadmin ThinkPHP5 宝塔环境 下Redis的使用教程

本篇为学习参考&#xff0c;不喜勿喷 此为宝塔windows环境下 1.首先在宝塔的安装面板&#xff0c;找到redis&#xff0c;点击安装。 2.安装完redis后&#xff0c;点击设置&#xff0c; 设置个密码(ps:留空代表没有设置密码) 3.php环境安装redis扩展&#xff08;ps:安装redis扩…

Linux学习笔记——Linux用户和权限管控

03、Linux用户和权限管控 3.1、认知root 用户 3.1.1、root用户&#xff08;超级管理员&#xff09; 1、无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。 在Linux系统中&#xff0c;拥有最大权限的账户名为&#xff1a;root&#xff08;超级管理员&#x…

赛狐ERP运营篇 | 店铺管理数智化 ,风险规避更有效!

亚马逊卖家在运营的当中会遇到以下这些问题&#xff1a; 1、工作重复度高&#xff0c;每天浪费大量的时间整理数据报表。 2、数据分析指标单一&#xff0c;无法掌握全局数据指标&#xff0c;综合分析Listing。 3、熬夜调广告&#xff0c;无法精准调整广告预算、竞价。 4、运…

2023年入职/转行网络安全,该如何规划?

前言 前段时间&#xff0c;知名机构麦可思研究院发布了 《2022年中国本科生就业报告》&#xff0c;其中详细列出近五年的本科绿牌专业&#xff0c;其中&#xff0c;信息安全位列第一。 网络安全前景 对于网络安全的发展与就业前景&#xff0c;想必无需我多言&#xff0c;作为…

c盘扩展卷选项是灰的怎么办?win10系统c盘扩展卷灰色

在Windows自带的磁盘管理工具中&#xff0c;用户想要对C盘进行扩容&#xff0c;c盘扩展卷选项是灰的怎么办&#xff1f; 那么&#xff0c;在本文中&#xff0c;易我小编将为您解答c盘分区扩展灰色的相关知识&#xff0c;帮你用户高效快捷地拓展C盘。 一、c盘分区扩展灰色的原因…

Android入门第52天-在SharedPreference中使用加密

简介 在上一篇中&#xff0c;我们讲了SharedPreference的使用。但是那不是一个生产场景。特别是我们举了一个例子&#xff0c;存放登录信息的例子。这个例子里用户的密码没有加密&#xff0c;比如说在真实的实际生产环境里用户的一些敏感信息或者说是像&#xff1a;用户四要素…

磁矢位的引入 工程电磁场 P19

首先我们有恒定磁场的两个方程 为了更方便解决问题&#xff0c;我们引入磁矢位 由此我们可以得到 我们可以得到 我们要确定A&#xff0c;则既需要知道旋度&#xff0c;我们还需要知道散度 如果是均匀媒质&#xff0c;是常数 我们可以得到 我们进行展开可以得到 我们要知道…

索引的底层实现及应用和失效场景

简介 合适的索引能让查询语句性能得到极大的优化&#xff0c;它只是优化业务的一种方式&#xff0c;不能为了建立索引而建立索引。 索引是什么&#xff1f; 索引是一种为了快速查找数据的数据结构&#xff0c;是帮助数据库快速获取数据的 排好序的数据结构 (BTree)。 索引的好…

鸿翼医药备份解决方案:守护医疗数据 携手共克时艰

新冠疫情期间&#xff0c;CT检查成为了明确诊断的重要手段&#xff0c;医学影像科迎来了检测人次的高峰。随着大量的医学影像数据的产生&#xff0c;影像数据占据了医疗数据总数的80-85%&#xff0c;占据了大量的系统存储空间。 我国医学影像数据的年增长率大约为30-40%&#x…

容器云的双活与灾备技术

在多中心多云环境下&#xff0c;可将容器云部署为多活和灾备模式&#xff0c;通过全局负载均衡器实现应用的多中心多活与灾备。容器应用跨数据中心的双活&#xff0c;是将一个应用的不同副本部署到不同的数据中心&#xff0c;如图 1 所示的 Database 应用。 图1 Database应用双…