字符串

字符串常用函数

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 判断是否有前缀
}
字符串的组成
  1. 字符串指向的底层字节数组

    字符串的中文占三个字节

  2. func main() {
       //fmt.Print(test())
       a := "我爱你"
       fmt.Println(a[:3]) //输出为"我"
    }
  3. 字符串的字节长度

字符串的底层结构在reflect.StringHeader中定义

type StringHeader struct{
  Data uinptr
  Len int
}

字符串本身是一个结构体,因此字符串的赋值操作也就是reflect.StringHeader结构体的复制过程,并不会涉及字节数组的复制 [2]string的底层结构和[2]reflect.StringHeader对应的底层结构是一样的,可以将字符串数组看作一个结构体数组

字符串的切片

字符串虽然不是切片但是支持切片操作,不同位置的切片底层访问的是同一块内存数据,因为字符串是只读的,所以相同的字符串面值变量通常对应同一个字符串常量

  1. 字符串和数组类似,可以通过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',一般显示为这个形状�

  1. 如果不想解码UTF8字符串,想直接遍历原始的字节码,可以将字符串强转为[]byte字节序列后再进行遍历
  2. 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的时候如果转换后的变量没有被修改,编译器可能直接返回原始的字符串对应的底层数据

#





posted @ 2019-12-19 19:53  离地最远的星  阅读(111)  评论(0编辑  收藏  举报