Go中的字符串
Go中的字符串
str1 := "Hello, world!" // 字符串定义
Go中的字符串由双引号""包围,且支持ASCII字符集以及UTF-8字符集。str2 := `This is a
multiline
string` // 支持换行和特殊字符
Go还支持原始字符串字面量,用反引号`包围,不会对字符串内容进行转义处理
- 字符串的长度和索引
Go字符串的长度是字符的字节数,而不是字符数。因为UTF-8编码的字符有可能占用多个字节。
获取字符串的字节长度:len(str)
获取字符的字节索引:str[i],i是字节索引(返回的是字节而不是字符)
str := "Hello, 世界!"fmt.Println(len(str)) // 14,字节数 空格也算fmt.Println(str[1]) // 101,返回字节
- 字符串是不可变的,所以不能像数组一样直接修改其元素,但可以通过切片(slice)对字符串进行操作。
str := "Hello, world!"slice := str[7:12] // 切片出 "world"fmt.Println(slice) // 输出: world
如果要获取字符,需要用rune类型
str := "Hello, 世界!"runeValue := []rune(str)fmt.Printf("%c", runeValue[7]) // 获取第7个字符(字符‘世’)
-
字符串拼接
Go提供了+操作符用于拼接字符串,但性能较差,尤其在多次拼接时,建议使用strings.Join()或strings.Builder。
str := "Hello, 世界!"runeValue := []rune(str)fmt.Printf("%c\n", runeValue[7]) // 获取第7个字符(从UTF-8编码看是字符‘世’)str1 := "Hello"str2 := "world"result := str1 + ", " + str2 // 使用 + 拼接fmt.Println(result) // 输出: Hello, world!words := []string{"Hello", "world"}result = strings.Join(words, ", ") // 输出: Hello, world
对于更复杂的拼接(如在循环中拼接多个字符串),strings.Builder是一个高效的选择。
它避免了字符串拼接中可能发生的内存重新分配,因为每次使用 + 运算符拼接字符串时,Go 会创建一个新的字符串,这样会导致不必要的内存分配和拷贝操作,尤其是在大量拼接字符串时会带来性能损失。
创建一个 strings.Builder 实例:
通过 var builder strings.Builder 或 builder := strings.Builder{} 创建一个 Builder 实例。
通过 WriteString 方法将字符串追加到 Builder 中。这个方法不会创建新的字符串,而是将数据直接追加到 Builder 的内部缓冲区。
使用 String() 方法可以返回构建好的字符串。
由于 Builder 是可变的,因此可以反复调用 WriteString 方法进行字符串拼接,而不会像使用 + 运算符那样频繁地进行内存分配。var builder strings.Builderbuilder.WriteString("Hello")builder.WriteString(", ")builder.WriteString("world")fmt.Println(builder.String()) // 输出: Hello, worldfmt.Println(builder.Len()) //12fmt.Println(builder.Cap()) //16Reset():重置 Builder,清空其内部的缓冲区,可以重新使用该实例。Len():返回当前 Builder 中内容的长度。Cap():返回 Builder 当前缓冲区的容量(即能够容纳多少字符)。
-
字符串的比较
Go语言提供了==、!=以及strings.Compare()等方式进行字符串比较。
str1 := "apple"str2 := "orange"fmt.Println(str1 == str2) // falsefmt.Println(strings.Compare(str1, str2)) // -1,表示str1小于str2
- 字符串查找
查找子串:strings.Contains()
查找子串的索引位置:strings.Index()
子串最后出现的位置:strings.LastIndex()
str := "Hello, world!"fmt.Println(strings.Contains(str, "world")) // truefmt.Println(strings.Index(str, "world")) // 7fmt.Println(strings.LastIndex(str, "o")) // 8
查找字符串中的多个子串的位置
package mainimport ("fmt""strings"
)func findAllIndexes(str, substr string) []int {var indexes []intstartIndex := 0for {// 查找子串的第一个出现位置index := strings.Index(str[startIndex:], substr)//这行代码返回substr在str中从startIndex位置开始出现的第一个位置。注意,它返回的是相对startIndex的索引,因此需要调整成绝对位置。if index == -1 {// 如果找不到了,退出循环break}// 计算绝对位置indexes = append(indexes, startIndex+index) //每次找到一个子串时,都会把它的绝对位置添加到indexes切片中,直到没有更多的子串为止。// 更新起始位置,继续查找下一个位置startIndex += index + 1 //使用startIndex来指定每次查找的起始位置。在找到一个子串的位置后,更新startIndex为当前子串的位置加1,然后继续查找下一个子串。}return indexes
}
func main() {str := "Go is Go, Go is fun!"substr := "Go"// 查找所有出现位置indexes := findAllIndexes(str, substr)// 输出结果fmt.Println("Substr appears at indices:", indexes) //Substr appears at indices: [0 6 10]
}
- 字符串替换
strings.Replace() 用于替换子串。
str := "Hello, world!"newStr := strings.Replace(str, "world", "Go", 1) // 将“world”替换为“Go”,只替换第一个fmt.Println(newStr) // 输出: Hello, Go!
- 字符串分割
strings.Split()用于将字符串按照指定分隔符拆分成切片。
str := "a,b,c"splitStr := strings.Split(str, ",") // 将字符串按逗号分割fmt.Println(splitStr) // 输出: [a b c]
- 字符串转大小写
Go提供了strings.ToUpper()和strings.ToLower()函数来分别将字符串转换为大写和小写。
str := "Hello, World!"fmt.Println(strings.ToUpper(str)) // 输出: HELLO, WORLD!fmt.Println(strings.ToLower(str)) // 输出: hello, world!
- 字符串修剪空白字符
strings.TrimSpace()会去掉字符串两端的空白字符。
str := " Hello, world! "trimmed := strings.TrimSpace(str) // 去除两端的空白字符fmt.Println(trimmed) // 输出: Hello, world!
- 字符串的转换
转为[]byte:使用[]byte(str)将字符串转换为字节切片。
转为[]rune:使用[]rune(str)将字符串转换为字符切片。
str := "Hello"bytes := []byte(str) // 将字符串转换为字节切片runes := []rune(str) // 将字符串转换为字符切片fmt.Println(bytes) // [72 101 108 108 111]fmt.Println(runes) // [72 101 108 108 111]一个字符(rune)可能由多个字节表示,因此需要使用rune而非byte进行字符处理。