Go从入门到放弃8--String

160 阅读2分钟

字符串是 Go 语言中的基础数据类型,虽然字符串往往被看做一个整体,但是它实际上是一片连续的内存空间,我们也可以将它理解成一个由字符组成的数组。

数据结构

type StringHeader struct {
	Data uintptr //指向字节数组的指针
	Len  int //数组的大小
}

Go 语言规定,字符串类型的值在它的生命周期内是不可改变的。我们直接将 string 类型通过函数 / 方法参数传入也不会带来太多的开销。因为传入的仅仅是一个“描述符”,而不是真正的字符串数据。

常见操作

下标操作

索引操作s[i]返回第i个字节的字节值,i必须满足0 ≤ i< len(s)条件约束,如果试图访问超出字符串索引范围的字节将会导致panic异常。

var s = "中国人"
fmt.Printf("0x%x\n", s[0]) // 0xe4:字符“中” utf-8编码的第一个字节

字符迭代

通过常规 for 迭代对字符串进行的操作是一种字节视角的迭代,每轮迭代得到的的结果都是组成字符串内容的一个字节,以及该字节所在的下标值,这也等价于对字符串底层数组的迭代。

var s = "中国人"
for i := 0; i < len(s); i++ {
  fmt.Printf("index: %d, value: 0x%x\n", i, s[i]) //index: 0, value: 0xe4
}

通过 for range 迭代,我们每轮迭代得到的是字符串中 Unicode 字符的码点值,以及该字符在字符串中的偏移值

var s = "中国人"
for i, v := range s {
    fmt.Printf("index: %d, value: 0x%x\n", i, v) //index: 0, value: 0x4e2d
}

字符串连接

Go原生支持通过 +/+= 操作符进行字符串连接

s := "Rob Pike, "
s = s + "Robert Griesemer, "
s += " Ken Thompson"

fmt.Println(s) // Rob Pike, Robert Griesemer, Ken Thompson

字符串比较

Go 字符串类型支持各种比较关系操作符,包括 = =、!= 、>=、<=、> 和 <。在字符串的比较上,Go 采用字典序的比较策略,分别从每个字符串的起始处,开始逐个字节地对两个字符串类型变量进行比较。

类型转换

当我们使用 Go 语言解析和序列化 JSON 等数据格式时,经常需要将数据在 string 和 []byte 之间来回转换,类型转换的开销并没有想象的那么小。

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

参考资料