字符串String

* 本页面主要介绍Go语言基本数据类型字符串String的相关内容。

Go语言中的字符串以原生数据类型出现,使用字符串就像使用其他原生数据类型(int、bool、float32、float64 等)一样。一个字符串是一个不可改变的字节序列。字符串可以包含任意的数据,包括byte值0,但是通常是用来包含人类可读的文本。

Go语言中的字符串的内部实现使用UTF-8编码。 字符串的值为双引号(")中的内容,可以在Go语言的源码中直接添加非ASCII码字符,例如:

  s1 := "hello, world"
  s2 := "凯冰科技"
  fmt.Println(len(s1))     // "12"
  fmt.Println(s1[0], s1[7]) // "104 119" ('h' and 'w')

内置的len函数可以返回一个字符串中的字节数目,索引操作s[i]返回第i个字节的字节值(0 ≤ i< len(s))。访问超出字符串索引范围的字节将会导致panic异常(panic: index out of range)。

一、字符串转义符

Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等,如下表所示。

转义 含义
\r 回车符(返回行首)
\n 换行符(直接跳到下一行的同列位置)
\t 制表符
\' 单引号
\" 双引号
\ 反斜杠

打印一个windows平台下的文件路径:

  fmt.Println("str := \"c:\\pprof\\main.exe\"")
二、多行文本

Go语言中要定义一个多行字符串时,就必须使用反引号字符。多行文本时,里面的转义字符将无效,文本将会原样输出。

  s1 := `第一行
    第二行
    第三行
    `
  fmt.Println(s1)
三、byte和rune类型

组成每个字符串的元素叫做“字符”,可以通过遍历或者单个获取字符串元素获得字符。 Go 语言的字符有以下两种:

  • uint8类型,或者叫 byte 型,代表了ASCII码的一个字符
  • rune类型,代表一个 UTF-8字符,实际是一个int32

rune类型在处理中文、日文或者其他复合字符时用到。

字符串底层是一个byte数组,所以可以和[]byte类型相互转换。

四、字符串的常见操作
1.截取

子字符串操作s[i:j]基于原始的s字符串的第i个字节开始到第j个字节(并不包含j本身)生成一个新字符串。i和j可忽略,i忽略时0作为起始位置,j忽略时,len(s)作为结束位置。

  fmt.Println(s[0:5]) // "hello"
  fmt.Println(s[:5]) // "hello"
  fmt.Println(s[7:]) // "world"
  fmt.Println(s[:])  // "hello, world"
2.连接

+操作符将两个字符串连接构造一个新字符串。还可使用fmt.Sprintf拼接字符串。

  fmt.Println("goodbye" + s[5:]) // "goodbye, world"
  title := fmt.Sprintf("goodbye%s", s[5:])

字符串连接操作+在数据量大时代价高昂,一种简单且高效的解决方案是使用strings包的Join函数:

  fmt.Println(strings.Join(s[1:], "zkbhj"))
3.比较

==和<进行比较,通过逐个字节比较完成的,因此比较的结果是字符串自然编码的顺序。

4.修改

字符串的值是不可变的:一个字符串包含的字节序列永远不会被改变。如下面的操作并不会改变t的值。当然尝试修改字符串内部数据的操作也是被禁止的。

  s := "left foot"
  t := s
  s += ", right foot"
  fmt.Println(s) // "left foot, right foot"
  fmt.Println(t) // "left foot"
  s[0] = 'L' // compile error: cannot assign to s[0]

不变性意味着如果两个字符串共享相同的底层数据的话也是安全的,这使得复制任何长度的字符串代价是低廉的。同样,一个字符串s和对应的子字符串切片s[7:]的操作也可以安全地共享相同的内存,因此字符串切片操作代价也是低廉的。在这两种情况下都没有必要分配新的内存。

字符串和两个子串共享相同的底层数据
字符串和两个子串共享相同的底层数据

变相的修改是,先把字符串强制转换为[]rune或[]byte,修改之后,再强制转换为string。

  func changeString() {
      s1 := "zkbhj.com"
      // 强制类型转换
      byteS1 := []byte(s1)
      byteS1[0] = 'Z'
      fmt.Println(string(byteS1))

      s2 := "凯冰科技"
      runeS2 := []rune(s2)
      runeS2[0] = '好'
      fmt.Println(string(runeS2))
  }
5.转换

字符串和数值之间的转换比较常见,这个可以通过 strconv包 提供的转换功能来实现。

  x := 123
  //用fmt.Sprintf返回一个格式化的字符串
  y := fmt.Sprintf("%d", x)
  //strconv.Itoa(“整数到ASCII”)
  fmt.Println(y, strconv.Itoa(x)) // "123 123"
  //用不同的进制来格式化数字
  fmt.Println(strconv.FormatInt(int64(x), 2)) // "1111011"
  //fmt.Sprintf函数附加额外信息
  s := fmt.Sprintf("x=%b", x) // "x=1111011"
  //Atoi字符串解析为整数
  x, err := strconv.Atoi("123")             // x is an int
  //ParseInt字符串解析为整数
  y, err := strconv.ParseInt("123", 10, 64) // base 10, up to 64 bits
6.其他操作
  len(str) //求长度
  data := strings.Split(s, ',') //分割
  data := strings.Contains(s, ',') //判断是否包含
  data := strings.HasPrefix(s, 'h') //前缀判断
  data := strings.HasSuffix(s, '!') //后缀判断
  data := strings.Index(s, '!') //子串出现的位置
  data := strings.LastIndex(s, '!') //子串出现的位置
  strings.Join(a[]string, sep string) // join操作(比+连接符更高效)
五、字符串面值

因为Go语言源文件总是用UTF8编码,并且Go语言的文本字符串也以UTF8编码的方式处理,因此我们可以将Unicode码点也写到字符串面值中。

一个原生的字符串面值形式是`...`,使用反引号代替双引号。原生字符串面值用于编写正则表达式会很方便,因为正则表达式往往会包含很多反斜杠。原生字符串面值同时被广泛应用于HTML模板、JSON面值、命令行提示信息以及那些需要扩展到多行的场景。

Go语言字符串部分的内容就总结到这里,你GET到了吗?


* 本页内容更新时间线:

  • 2021年2月18日 16:03:01 : 知识复习 & 勘误更新
  • 2020年11月6日 21:00:15 : 创建文档

* 本页内容参考以下数据源:

  • 《Go程序设计语言》

凯冰科技 · 代码改变世界,技术改变生活
Next Page→