无论在哪种语言里,字符串都是一种相当重要的数据类型。很多语言都有字符串的概念,但是又有很大区别。比如 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. java获取下一季末_java取当前周期、月初至月末、季度初至季度末日期。
  2. Port already be taken
  3. matlab画平行坐标轴的直线
  4. 第十二周项目1-阅读程序(三)
  5. VSCode中屏蔽文件files.exclude和屏蔽文件搜索search.exclude
  6. 多样化实现Windows Phone 7本地数据访问3——DB4O
  7. 如何用ABAP代码读取SAP Business partner的附件数据
  8. javaone_JavaOne 2012 – 2400小时! 一些建议
  9. python selenium po_python+selenium基于po模式的web自动化测试框架
  10. mysql2005错误码_SQL Server2005 常见错误及解决方案
  11. ubuntu 12.04 安装intel i5-6500 的集成网卡驱动【自身经历,验证OK】
  12. java socket监听_Java -socket接口(监听)
  13. Latex绘制三线表
  14. 故宫,中国古代建筑艺术的奇葩
  15. 【开发工具】MySQL免安装版
  16. Foxmail 设置自动落款签名
  17. 极米Z6X Pro值得购买吗?这篇评测告诉你
  18. .obj 和 .mtl文件格式
  19. 在Linux下测试SD卡的读写速度
  20. Java开源的11个中文分词器使用方法和分词效果对比

热门文章

  1. Vlan 技术 (完整)
  2. WebSphere V8.5 静默安装升级(一)-独立安装每个安装包
  3. JS语言是怎么被运行的
  4. 理解dockerfile是如何工作的?
  5. 计算机音乐我和你,《我和你》音乐教案
  6. 从IOC的一些实际情况谈对其的评价标准
  7. JavaScript:inherits
  8. Redis列表数据类型
  9. Mac电脑安装及终端命令使用mysql
  10. 指纹定位蓝牙打点工具