八、Go语法基础(字符串)

24 阅读3分钟

Golang中文学习文档地址

在 Go 中,字符串本质上是一个不可变的只读的字节数组,也是一片连续的内存空间。

1、字面量

  • 普通字符串

    使用""双引号,支持转义,不支持多行(要换行只能使用/n转义)。

    func main() {
        fmt.Println("hello \nword")
    }
    //输出
    //hello 
    //word
    
  • 原生字符串

    使用反引号``,不支持转义,支持多行,原生字符串里的字符会原封不动的输出。

    func main() {
        fmt.Println(`hello
    word`)
    }
    //输出
    //hello 
    //word
    

2、字符串的访问

  • 字符串本质是字节数组,所以字符串的访问和数组的访问一样的。

  • 字符串无法修改,只能覆盖。

    import "fmt"
    
    func main() {
            //字符串的修改
            str := "hello world"
            //str[0] = 'H' //无法修改,无法通过编译。
            fmt.Println(str)
            str = "new hello world"//允许覆盖
            fmt.Println(str)
    
            //字符串的转换
            bytes := []byte(str) //将字符串转成byte数组,属于复制行为,将str的值复制一份,赋值给新的内存地址。
            fmt.Println(bytes)
    
            bytes[0] = 'H' //修改的是新的字符串byte
            fmt.Println("old string: ", str,
                    " new string: ", string(bytes))
    }
    

3、字符串的长度

字符串的长度,其实并不是字面量的长度,而是字节数组的长度,只是大多数时候都是ANSCII字符,刚好能用一个字节表示,所以恰好与字面量长度相等,求字符串长度使用内置函数len

import (
	"fmt"
	"unicode/utf8"
)

func main() {
	str1 := "hello world"                   //一个英文字母占一个字节
	str2 := "你好 世界"                     //在unicode中,一个中文字符,占三个字节
	fmt.Println(len(str1), len(str2))      //11 13,len函数计算的字节数
	fmt.Println(utf8.RuneCountInString(str1), utf8.RuneCountInString(str2)) //11 5,计算的是unicode字符数
}

4、字符串的拷贝

  • 拷贝的两种方式:内置函数copystring.clone函数。
import (
	"fmt"
	"strings"
)
func main() {
	str := "Hello World"
	fmt.Println("old string:", str)
	//使用内置函数完成copy
	newStr := make([]byte, len(str)) //先根据原字符创建字节数组
	copy(newStr, str)
	fmt.Println("copy string:", string(newStr))

	//使用strings.clone
	cloneStr := strings.Clone(str)
	fmt.Println("clone string:", cloneStr)
}

5、字符串的拼接

  • 性能较差的两种方式(适合对性能要求不高的场景)

    • 使用+拼接
    import (
    "fmt"
    )
    func main() {
            str1 := "hello"
            str2 := "world"
            str3 := str1 + str2
            fmt.Println(str3)
    }
    
    • 使用字节数组拼接
    import (
    "fmt"
    )
    func main() {
           str1 := "hello "
           str2 := "world1"
           bytes1 := []byte(str1)
           bytes := append(bytes1, str2...)
           fmt.Println(string(bytes))
    }
    
  • 性能要求高场景下:strings.Builder

import (
	"fmt"
	"strings"
)
func main() {
	builder := strings.Builder{}
	builder.WriteString("hello ")
	builder.WriteString("world ")
	builder.WriteString("go")
	fmt.Println(builder.String())
}

6、字符串的遍历

  • 使用for遍历字符
import "fmt"

func main() {
    str := "Hello World,第一个程序!"
    //本质上遍历的是字节数组
    //如果字符为英文字符,则刚好是一个字节
    //如果字符为中文字符,则一个中文字符需要占3个字节,而遍历时,只有一个字节,所以产生乱码
    for i := 0; i < len(str); i++ {
       fmt.Printf("%c", str[i])
    }
}
  • 使用for range遍历
import "fmt"

func main() {
    str := "Hello World,第一个程序!"
    //for range中,r的单位是一个rune(将str默认转成[]rune)
    //rune本质上是int32,最大容量是3个字节,刚好存储一个中文字符,所以输出中文不会乱码
    for i, r := range str {
       fmt.Println(i, string(r))
    }
}
  • 使用uft8包下的函数
func main() {
  str := "hello 世界!"
  for i, w := 0, 0; i < len(str); i += w {
    r, width := utf8.DecodeRuneInString(str[i:])
    fmt.Println(string(r))
    w = width
  }
}