【Go】11、golang字符串

  • 一个Go语言字符串是一个任意字节的常量序列
1、Go语言字符串字面量
  • 在Go语言中,字符串字面量使用双引号""或者反引号``(esc下面的那个)来创建
  • 双引号用来创建可解析的字符串,支持转义,但不能用来引用多行
  • 反引号用来创建原生的字符串字面量,可能有多行组成,但不支持转义,并且可以包含除了反引号外其他的所有字符
  • 双引号创建可解析的字符串应用最广泛反引号用来创建原生的字符串则多用于书写多行消息、HTML以及正则表达式
  • 举例:
package main

import "fmt"

func zfc() {
	var s string = "hello world"
	var s1 = "hello world"
	s2 := "hello world"

	fmt.Printf("s: %v\n", s)
	fmt.Printf("s1: %v\n", s1)
	fmt.Printf("s2: %v\n", s2)

	s4 := `
		line1
		line2
		line3
	`
	fmt.Printf("s4: %v\n", s4)
}

func main() {
	zfc()
}
# 输出结果:
    s: hello world
    s1: hello world
    s2: hello world
    s4: 
            line1
            line2
            line3
2、go语言字符串连接
  • 使用+加号
    • 虽然go语言中的字符串是不可变的,但是字符串支持+级联操作和+=追加操作,例如:
func test2() {
	// 字符串连接 + 和 += 
	s1 := "tom"
	s2 := "20"
	msg := s1 + s2
	fmt.Printf("msg: %v\n", msg)
	fmt.Printf("--------------")
	msg1 := ""
	msg1 += s1
	msg1 += " "
	msg1 += s2
	fmt.Printf("msg1: %v\n", msg1)
}
func main() {
	test2()
}
    • golang里面的字符串都是不可变的每次运算都会产生一个新的字符串,所以会产生很多临时的无用的字符串,不仅没有用,还会给gc带来额外的负担,所以性能比较差
  • 使用fmt.Sprintf()函数
func test3() {
	// 字符串拼接
	s1 := "tom"
	s2 := "20"
	msg := fmt.Sprintf("%s, %s", s1, s2)
	fmt.Printf("msg: %v\n", msg)
}
func main() {
	test3()
}

# 输出结果:
    msg: tom, 20
    • 内部使用[]byte实现不像直接运算符这种会产生很多临时的字符串,但是内部的逻辑比较复杂,有很多额外的判断,还用到了interface,所以性能也不是很好
  • strings.Join()
func test4() {
	name := "tom"
	age := "20"
	msg := strings.Join([]string{name, age}, ",")
	fmt.Printf("msg: %v\n", msg)
}
func main() {
	test4()
}
# 输出结果
    msg: tom,20
    • join会先根据字符串数组的内容,计算出一个拼接之后的长度,然后申请对应大小的内存,一个一个字符串填入,在已有一个数组的情况下,这种效率会很高,但是本来没有,去构造这个数据的代价也不小
  • buffer.WriteString()
func test5() {
	var buffer bytes.Buffer

	buffer.WriteString("tom")
	buffer.WriteString(",")
	buffer.WriteString("20")
	fmt.Printf("buffer.String(): %v\n", buffer.String())
}

func main() {
	test5()
}
# 输出结果:
	buffer.String(): tom,20
    • 这个比较理想可以当成可变字符使用,对内存的增长也有优化,如果能预估字符串的长度,还可以用buffer.Grow()接口来设置capacity
3、go语言字符串转义字符
  • Go语言的字符串常见转义符包含回车、换行、单双引号、制表符等,如下表所示
转义符含义
\r回车符(返回行首)
\n换行符(直接跳到下一行的同列位置)
\t制表符
\'单引号
\"双引号
\\反斜杠
4、go语言字符串切片操作
func test7() {
	// 字符串切片操作
	str := "hello world"
	n := 3
	m := 5
	fmt.Println(str[n]) // 获取字符串索引位置为n的原始字节
	fmt.Println(str[n:m]) // 截取的字符串索引位置为n到m-1的字符串
	fmt.Println(str[n:]) // 截取得字符串索引位置为n到len(s)-1的字符串
	fmt.Println(str[:m]) // 截取得字符串索引位置为0到m-1的字符串
}
func main() {
	test7()
}

# 输出结果
    108
    lo
    lo world
    hello
5、go语言字符串常用方法
方法介绍
len(str)求长度
+或fmt.Sprintf拼接字符串
strings.Split分隔
strings.contains判断是否包含
strings.HasPredix,
strings.HasSuffix
前缀/后缀判断
strings.Index(),
strings.LastIndex()
子串出现的位置
strings.Join(a[]string, step string)join操作
strings.ToUpper字符串大写
strings.ToLower字符串小写
func test8() {
	// 常用方法
	s := "hello world"
	fmt.Printf("len(s): %v\n", len(s))
	s1 := "go"
	result := s + " " + s1
	fmt.Printf("result: %v\n", result)
	result1 := fmt.Sprintf("%s, %s", s, s1)
	fmt.Printf("result1: %v\n", result1)
	fmt.Printf("strings.Split(s, \" \"): %v\n", strings.Split(s, " "))
	fmt.Printf("strings.HasPrefix(\"hello\"): %v\n", strings.HasPrefix(s, "hello"))
	fmt.Printf("strings.HasSuffix(s, \"ld\"): %v\n", strings.HasSuffix(s, "ld"))
	fmt.Printf("strings.Index(s, \"l\"): %v\n", strings.Index(s, "l"))
	fmt.Printf("strings.LastIndex(s, \"l\"): %v\n", strings.LastIndex(s, "l"))
	fmt.Printf("strings.ToUpper(s): %v\n", strings.ToUpper(s))
	fmt.Printf("strings.ToLower(s): %v\n", strings.ToLower(s))
}
func main() {
	test8()
}
# 输出结果:
len(s): 11
result: hello world go
result1: hello world, go
strings.Split(s, " "): [hello world]
strings.HasPrefix("hello"): true
strings.HasSuffix(s, "ld"): true
strings.Index(s, "l"): 2
strings.LastIndex(s, "l"): 9
strings.ToUpper(s): HELLO WORLD
strings.ToLower(s): hello world
posted @ 2022-06-13 17:57  郭祺迦  阅读(979)  评论(0)    收藏  举报