字符串处理,一般是可以单独立一章讲解的。看看Golang的字符串处理。
一、string、byte这两个都常见。Golang的string,底层是[]byte。对于ASCII字符,Golang默认用1字节;对于汉字,Golang使用UTF-8字符集存储,默认用三个字节。
看个例子,下面的“我爱学习”三个汉字就各占3字节。
package main
import "fmt"
func main() {
var str1 string = "123我爱学习"
fmt.Println(len(str1))
}
//输出结果:
15
字符串默认在堆上分配内存存储,是不可变的字节数组,其头部指针指向一个字节数组。
string在内存中的存储结构是长度固定的字节数组,也就是说是字符串是不可变的。当要修改字符串的时候,需要转换为[]byte,修改完成后再转换回来。但是不论怎么转换,都必须重新分配内存,并复制数据,通过加号拼接字符串,每次都必须重新分配内存。
二、byte约等于int8,处理汉字是不合适的。
看下面的例子:
package main
import (
"fmt"
"reflect"
)
func main() {
var str1 string = "123我爱学习"
for i:=0; i<len(str1);i++ {
fmt.Println(str1[i])
fmt.Println(reflect.TypeOf(str1[i]))
}
}
//输出结果:
49
uint8
50
uint8
51
uint8
230
uint8
136
uint8
145
uint8
231
uint8
136
uint8
177
uint8
229
uint8
173
uint8
166
uint8
228
uint8
185
uint8
160
uint8
三、Golang有一种类型rune,处理字符串里的UTF-8很适合。
先看看如果直接用range循环字符串的例子:
package main
import (
"fmt"
"reflect"
)
func main() {
var str1 string = "123我爱学习"
for _, v := range str1 {
fmt.Println(v)
fmt.Println(reflect.TypeOf(v))
}
}
//运行结果:
49
int32
50
int32
51
int32
25105
int32
29233
int32
23398
int32
20064
int32
直接是int32类型值,无法看懂。
package main
import (
"fmt"
)
func main() {
var str1 string = "123我爱学习"
rr := []rune(str1)
for i:=0; i<len(rr);i++ {
fmt.Printf("%c \n",rr[i])
fmt.Println(reflect.TypeOf(rr[i]))
}
}
//输出结果:
1
int32
2
int32
3
int32
我
int32
爱
int32
学
int32
习
int32
rune实际上就是int32,只不过用来表示字符。
四、小结:
- byte 等同于int8,常用来处理ascii字符
- rune 等同于int32,常用来处理unicode或utf-8字符
- string放在堆,底层是byte[],不可修改。如果一定要改,转成[]byte。