无论在哪种语言里,字符串都是一种相当重要的数据类型。很多语言都有字符串的概念,但是又有很大区别。比如 c 语言里,需要使用一个以 '\0' 结尾的字节数组来表示字符串;c++ 里使用 std::string 类型表示字符串;在 java 里是 String. 在这些语言里,字符串并不是一种基础数据类型,而是更加复杂的复合类型,或者『类』类型。

接下来即将讨论的 go 语言里的字符串,它就是一种基础数据类型,和上面那些语言有着相当大的区别。

1. 不可变的字符串

go 里的字符串,是不可变的字节序列(immutable sequence of bytes). 这句话有两层含义:

  • 不可变 (immutable)
  • 字节序列(sequence of bytes)

第二点在后面的第 2 节里说明。这里先看第一点。

在 go 语言里,字符串是基本类型,这一点和 python/nodejs 语言非常像。具体一点,我们说字符串是一个不可分割,不可修改的整体。举 2 个反例:

  • c 语言
char s[] = "abcde";
s[0] = 'f';
  • c++ 语言
std::string s = "abcde";
s[0] = 'f';

在上面的例子中,对字符串进行修改是合法的。然而,这种修改似乎破坏了字符串的整体性。一个字符串,它就像一个完整的人,它的局部不应该被随随便便更改才对。

在 go 语言里,下面的操作是不合法的:

var s string = "abcde"
s[0] = 'f'; // not ok

可能你会着急问,如果要修改怎么办?这个问题解决起来很简单,创建一个新的字符串就行了。在 go 里你可以这么处理:

var s string = "abcde"
var t string = "f" + s[1:] // 创建一个新字符串

2. 遍历字符

刚刚我们看到了,要想访问字符串的『字符』我们使用下标就可以做到。但是还有一点点小问题,稍后再说,先来看一个例子:

var s string = "abcde"// len 函数是 go 的内置函数,可以计算字符串的长度。在第一章节我们也用过,还记得吗?
for i := 0; i < len(s); i++ {fmt.Printf("%c\n", s[i])
}

最后会输出:

a
b
c
d
e

下面来看第二个例子:

var s string = "你好,世界"// len 函数是 go 的内置函数,可以计算字符串的长度。在第一章节我们也用过,还记得吗?
for i := 0; i < len(s); i++ {fmt.Printf("%c\n", s[i])
}

运行后输出:


图1 输出字符???

首先这个输出是什么鬼?难道不认识中文吗?还是中文太博大精深了?这里有两点需要注意:

  • 字符串的下标一次只索引一个字节数据
  • 字节 != 字符

在 ascii 码里,字节和字符是一致的,但是到了汉字世界,就不成立了。

先解释一下乱码的原因:在 go 里,源文件使用 utf-8 进行编码。也就是说你写在源文件里的 “你好,世界” 也是 utf-8 编码的。程序运行后,在 go 语言的内存里,这个字节序列保存的也是 utf-8 字节序列(注意这里我提到了字节序列)。而 go 的下标一次只索引一个字节的数据,因此你每次索引的只是 utf-8 字节序列的某一个部分,看到的当然是个乱码。

如何正确遍历字符这个问题放到后面的博客里解决,这里先暂放一放。继续下一个话题。

3. 字符串切片

说到字符串切片,大多数人就想到了 python. 没错,go 里的切片也很强大,强的接近 python……好吧,go 的字符串切片已经相当不错了,至少比 c++ 语言字符串要强大 10000 万倍了是不。

可能有同学还不知道切片是什么意思,其实它就是取子串,即得指定范围的 substring. 举例:

var s string = "Hello, world"a := s[2:]  // "llo, world"
b := s[:5]  // "Hello"
c := s[2:5] // "llo"

go 的切片没有 Python 强,是因为 Python 还支持使用负数做索引(有点逆天是不)。不过我们的 go 是静态语言,能做到这样,也已经很牛逼了!

接下来,我们再回顾一下『不可变』的含义,它背后隐藏的目的是什么?

  • 可变性带来的缺点

不妨假设字符串 s 是可变的,我们执行 s[2] = 'x' ,会不会导致字符串 a 变成 "xlo world"? 很明显,我们不希望这件事情发生,因为字符串 s 和 a 本来就是不相干的。

如此一来,为了防止字符串 a 和 s 产生关联,我们又需要为 a 重新开辟一块内存空间,将 s[2:]的内容复制到新的空间去。

  • 不可变的优势

好了,『可变』的字符串为切片操作带来了困扰。那如果是『不可变』的呢?这意味着字符串 a 可以继续使用 s 的内存,而不必再开辟新空间!因为字符串 s 本来就是不可变的,所以共享它的内存是安全的。


图2 『不可变』字符串的好处是可以共享内存

这个特性会让字符串的复制和切片操作变得非常低廉,因为它没有任何开辟新内存和拷贝字节的代价!

4. 总结

  • 掌握字符串类型

031-神奇的字符串相关推荐

  1. 【PHP】`异客塞尔`世界 与 神奇的字符串++

    目录 [PHP]`异客塞尔`世界 与 神奇的字符串++ 通往`异客塞尔`世界 独特编号破坏了异世界的`优雅` 神奇的`++`带来了和平 初寻的`++`的真相 [PHP]异客塞尔世界 与 神奇的字符串+ ...

  2. 神奇的字符串-包含26个字母

    PG 如果一个字符串包含了所有的字符(a到z,不区分大小写),那么我们就说这是一个神奇的字符串. 现在,给你一个由大写和小写字母组成的字符串,判断其是否为神奇的字符串. Input 第一行包含一个整数 ...

  3. 【Python】Python中神奇的字符串驻留机制

    今天有一个初学者在学习Python的时候又整不会了. 原因是以下代码: a = [1, 2, 3] b = [1, 2, 3] if a is b: print("a and b point ...

  4. 【每日一题】031 神奇的6位数

    题目详情: 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可. 有一个 6位的正整数,它有个很神奇的性质: 分别用2,3,4,5,6 去乘它,得到的仍然是 6 位数,并且乘积中所 ...

  5. 1.神奇的字符串之快速求和

    文章目录 前言 正题 先看第一个代码 直接循环取出每一位数 总结 . 前言 这个专栏是分享一些好用的数据 和一些解题比较快的小方法 会持续更新 因为博主还是计算机方向的小白 知道的东西还是很少 希望大 ...

  6. 4417. 神奇的字符串

    Solution: 我们要求出以j点为开头的长度为m的子串有多少位和s不同,等价于求c[j]与s[0]不同,c[j + 1]与s[1]不同,c[j + 2] 与s[2] 不同....... c[j + ...

  7. LeetCode 481. 神奇字符串(找规律)

    1. 题目 神奇的字符串 S 只包含 '1' 和 '2',并遵守以下规则: 字符串 S 是神奇的,因为串联字符 '1' 和 '2' 的连续出现次数会生成字符串 S 本身. 字符串 S 的前几个元素如下 ...

  8. Java实现 LeetCode 481 神奇字符串

    481. 神奇字符串 神奇的字符串 S 只包含 '1' 和 '2',并遵守以下规则: 字符串 S 是神奇的,因为串联字符 '1' 和 '2' 的连续出现次数会生成字符串 S 本身. 字符串 S 的前几 ...

  9. alxc tool 报错数组超出了界限_代码审计之报错信息泄露与字符串截断

    机器在语言编码转换的时候,经常会出现各种各样的异常,这些神奇的字符串就有可能组合成一堆乱码出来,也有可能直接把程序搞崩溃掉,不过总有那么一些字符,可以帮助我们在利用漏洞的时候变得更简单一些,下面我们就 ...

  10. php数据类型之字符串

    字符串就是所有我们可见和不可见的字符,就是我们日常当中说的话,就是我想说:"小明好帅"或者"凤姐,我爱你!".字符串,就是我想表达的一切让人看到的字符. 例如可 ...

最新文章

  1. mysql执行计划中性能最差的是_面试中:mysql性能调优-执行计划explain
  2. 5G+SD-WAN实现更多应用的可能-vecloud微云
  3. OpenOffice介绍
  4. dotnet 从零开始写一个人工智能 网络模型
  5. Visual Studio 2010 单元测试之一---普通单元测试:http://blog.csdn.net/tjvictor/archive/2011/02/09/6175362.aspx...
  6. sublime 安装 Package Control(笔记)
  7. JOSN的stringify()和parse()方法
  8. vue ----vue-cli
  9. 六款值得推荐的android(安卓)开源框架简介
  10. 从技术到应用实践,揭秘京东区块链布局全景
  11. CentOS6.5安装python3.7
  12. vc ctabctrl页面切换事件_10191025一周PE/VC事件回顾|猿辅导获得10亿美元G2轮融资
  13. 什么是EDI报文标准?
  14. html5 lang属性都有哪些语言,HTML5中的lang属性,zh
  15. JavaWeb前端: JavaScript 简介
  16. 祭奠自己逝去的三年时光
  17. 拼团返利模式玩法VS最新拼团的商业模式
  18. 生成drl文件_drools原生drl规则文件的使用
  19. Eclipse里看到project 存在向上或者向下的箭头
  20. stm32f4xx标准外设固件库

热门文章

  1. css规则中区块block,CSS 定位详解
  2. Linux各个系统版本及区别的最全总结
  3. 基础算法:直接插入排序
  4. JavaScript语言核心
  5. 齐岳提供NIR近红外二区染料 TTQ-TF、TTQ-TTF、 TTQ-PLL、TTQ-F 、TTQ-TF、TTQ-TPA、 TTQ-PLL、TTQ-TC用于化疗-光热联合治疗
  6. 图像形态学轮廓处理人脸边缘轮廓提取(下巴、嘴唇)
  7. [附源码]JAVA+ssm计算机毕业设计仓库物资信息可视化管理系统(程序+Lw)
  8. 日语二级重要词汇之形容词/形容动词100
  9. 如何将一首网易云音乐,生成一个音乐二维码?
  10. 洛谷刷题笔记 分糖果