liqiang 的博客.

Go 语言中的字符串

Word count: 1,288 / Reading time: 5 min
2018/08/18 Share

在 Go 语言中,字符串作为一个内置的类型,被广泛得使用,但是,虽然被用得多,你知道的未必多。在使用字符串的过程中,确实有很多不确定点可能会让代码的编写有一些被动的情况,例如在字符串和其他类型之间转换,如何传递字符串,如何比较字符串和如何切割字符串比较高效等,这些都是需要去考虑的问题。所以,我想一次性将这些问题都解决掉,因此在这篇文章中你都能看到这些问题的解答,以及更多的其他关于 Go 语言中字符串的知识。

string 的内部结构

在 Go 语言的官方说明中,强调了 Go 语言的 string 的定义是:a string in effect a read-only slice of bytes,也就是说从内部的实现来说,string 的定义应该是这样的:

也就是说其实 Go 的实现是封装了一种方式,让我们将一个字符串 literal 转换为 byte 数组,然后记录下字符串的长度,所以我们可以用一下的方式来简单验证一波:

这里介绍得比较简单,但是,我们对 string 的内部结构有了一个简单的了解,后面的东西可能就比较好接受了,所以继续;

关于 string 的一些总结

前面只是简单得分析了一下 string 的组成,下面接着说一些在 Go 里面,对于 string 的概念:

  • 虽然 string 的结构是 slice ,但是 string 的类型在 Go 语言里面是常量,也就是一旦创建,不能修改里面的值(不代表不能修改一个 string 变量的值,关系类同常量指针);
  • Go 支持两种类型的定义方式,分别是双引号(\”\”)和 反引号(``),双引号就是普通的字符串,但是反引号会保留一定的格式;
  • string 类型的默认值或者说零值是 “” 或者 ``;
  • string 类型可以通过 ++= 操作连接;
  • string 类型可以通过 “==” 或者 “!=” 进行内容比较,但是后面会说到一个小坑;
  • string 本身没有任何方法可以调用,一些通用的操作(例如字符串分割,高效的合并等)可以通过 strings 这个 package 中的辅助函数进行;
  • 可以通过数组的索引下标方式获取某个字符(str[0])或者一段子串(str[0:10]);

字符串和字符

前面说了,字符串是 byte 的组合,为啥是 byte 而不是字符呢?这就涉及到计算机里面关于字符的定义了,在通用意义上,所谓的字符是一个完整的可打印的表达,例如对于英文单词:”hi”,我们通常会认为这是由两个字符:’h’ 和 ‘i’ 组成;对于中文词组:”我们”,通常也会认为是由两个字符:’我’ 和 ‘们’ 组成。但是,对于计算机来说,却不是这样的,英文单词因为历史的缘故(ASCII),大多数表示法中都和我们的通用认识是一致的,”hi” 是由两个字符组成,但是,对于 “我们” 这个词组,各种表示法有不同的看法,不过有一点是基本一致的,那就是 “我们” 不能用 2 个 byte 表示出来,所以很可能我们通用意义上的两个字符的 “我们” 在计算机中是 4-6 个 byte,那么对于有中文也有英文的场景,我们要如何定义 ‘字符’ 的概念呢?

这里 Go 给出了自己的答案,在 Go 中,不去关注你用什么表示法,我只管用 byte 来存储数据,至于你通用意义上的字符,Go 抽象出了一个 rune 的类型,这是一个 int32 的 alias,如果你需要区分通用概念上的字符时,可以使用它,下面我就给一个例子来表达一下 Go 的处理方式:

这里有几个地方是需要说的:

  • Go 里面的单引号 '' 的作用就是定义 rune 的常量;
  • Line 7 是非法的,你通不过编译,因为前面说了字符串是 []byte,所以 strB[0] 的类型是 byte 不能和 rune 对比;
  • Line 8 展示了如果你需要通用意义上的字符的操作,需要转换成 []rune
  • Line 9Line 10 对比可以发现,这个 '⌘' 占了 3 个 byte 的大小。

字符串和其他类型的转换

可能在实际使用过程中,用的比较多的字符串转换是和数字类型的转换,这里就展示两种不同类型的转换,其他类型应该都大同小异,这里只是抛个砖:

可以发现这里其实还是比较简单的,但是有个不爽的地方是可以发现在 Line 5Line 7 都忽略了 error,所以对于一些场景,可以尝试自己封装一个 MustAtoi,这样更舒服一些。

Reference

  1. Strings, bytes, runes and characters in Go
  2. Strings In Go
CATALOG
  1. 1. string 的内部结构
  2. 2. 关于 string 的一些总结
  3. 3. 字符串和字符
  4. 4. 字符串和其他类型的转换
  • Reference