字符串
基本介绍
一个字符串是一个不可改变的字节序列,字符串通常是用来包含人类可读的文本数据。和数组不同的是,字符串的元素不可修改,是一个只读的字节数组。每个字符串的长度虽然也是固定的,但是字符串的长度并不是字符串类型的一部分。 由于Go语言的源代码要求是UTF8编码,导致Go源代码中出现的字符串面值常量一般也是UTF8编码的。源代码中的文本字符串通常被解释为采用UTF8编码的Unicode码点(rune)序列。因为字节序列对应的是只读的字节序列,因此字符串可以包含任意的数据,包括byte值0。我们也可以用字符串表示GBK等非UTF8编码的数据,不过这种时候将字符串看作是一个只读的二进制数组更准确,因为**for range等语法并不能支持非UTF8编码的字符串的遍历。**
Go语言字符串的底层结构在reflect.StringHeader中定义:
type StringHeader struct {
Data uintptr
Len int
}
字符串结构由两个信息组成:
- Data是指向的底层字节数组
- Len是字符串的字节长度
字符串其实是一个结构体,因此字符串的赋值操作也是reflect.StringHeader结构体的复制过程,并不会涉及底层字节数组的复制。
字符串“hello world"对应的内存结构 ![[截屏2022-07-09 下午3.36.38.png]] 字符串虽然不是切片但是支持切片的操作
s := "hello, world"
hello := s[:5]
world := s[7:]
s1 := "hello, world"[:5]
s2 := "hello, world"[7:]
字符串的迭代与赋值
- 默认迭代方式
for i,c := range "你好世界"{
fmt.Println(i,c)
}
/*
0 20320
3 22909
6 19990
9 30028
*/
go中for range 字符串默认是以utf8解码后的unicode码点作为值遍历的如果想以字节数组的方式遍历可以加上强转 2. 以byte数组方式便利
for i,c := range []byte("你好世界"){
fmt.Println(i,c)
}
/*
0 228
1 189
2 160
3 229
4 165
5 189
6 228
7 184
8 150
9 231
10 149
11 140
*/
Go语言除了for range 语法对UTF8字符串提供了特殊支持外,还对字符串和[]rune类型的相互转换提供了特殊的支持
fmt.Printf("%#v\n",[]rune("世界")) //[]int32{19990,30028}
fmt.Printf("%#v\n",string([]rune{'世','界'})) //世界