字符串常用函数
package main
import (
"fmt"
"strings"
)
func main() {
str := "I love my work and i love my family too"
ret := strings.Split(str, " ")
fmt.Println(ret) //[I love my work and i love my family too]
ret = strings.Fields(str) //只能按空格拆分
fmt.Println(ret) //[I love my work and i love my family too]
fmt.Println(strings.HasSuffix(str, "too")) //true 判断是否有后缀
fmt.Println(strings.HasPrefix(str, "I")) //true 判断是否有前缀
}
字符串的组成
- 字符串指向的底层字节数组
字符串的中文占三个字节
func main() { //fmt.Print(test()) a := "我爱你" fmt.Println(a[:3]) //输出为"我" }
- 字符串的字节长度
字符串的底层结构在reflect.StringHeader中定义
type StringHeader struct{
Data uinptr
Len int
}
字符串本身是一个结构体,因此字符串的赋值操作也就是reflect.StringHeader结构体的复制过程,并不会涉及字节数组的复制 [2]string的底层结构和[2]reflect.StringHeader对应的底层结构是一样的,可以将字符串数组看作一个结构体数组
字符串的切片
字符串虽然不是切片但是支持切片操作,不同位置的切片底层访问的是同一块内存数据,因为字符串是只读的,所以相同的字符串面值变量通常对应同一个字符串常量
- 字符串和数组类似,可以通过len函数返回字符串的长度,也可以通过reflect.StringHeader结构访问字符串的长度
s := "helloworld" fmt.Println("len(s): ",(*reflect.StringHeader)(unsafe.Pointer(&s)).Len) //10
字符串编码问题
根据Go语言规范,Go语言的源文件都采用UTF编码,因此,Go源文件中出现的字符串面值常量一般也是UTF8编码的,对于转义字符没有这个限制,直接遍历字符串得到的是UTF9解码后的Unicode码点值
s := "hello world"
for _, v := range s {
fmt.Print(v, ",") //104,101,108,108,111,32,119,111,114,108,100,
}
在Go语言中,字符串可以存放任意的二进制字节序列,而且即使是UTF8字符序列也可能会遇到错误的编码,如果遇到一个错误的UTF8编码输入,将生成一个特别的Unicode字符 'uFFFD',一般显示为这个形状�
- 如果不想解码UTF8字符串,想直接遍历原始的字节码,可以将字符串强转为[]byte字节序列后再进行遍历
for i, c := range []byte("世界abc"){ fmt.Println(i, c) //这里会输出9次,因为在Go语言中,中文占3个字符 }
rune
rune其实是int32类型,这里的rune只是int32的别名,并不是重新定义的类型,rune用于表示每个Unicode码点,目前只使用了21个位,因为字符串的底层是[]byte,rune是[]int32所以他们之间的转换可能会造成重新分配内存的操作,字符串转byte的时候如果转换后的变量没有被修改,编译器可能直接返回原始的字符串对应的底层数据
#