在 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 的概念:

字符串和字符

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

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

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

字符串和其他类型的转换

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

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

Reference

  1. Strings, bytes, runes and characters in Go
  2. Strings In Go