05 string 的使用和实践
string是一种基本数据类型,用于表示不可变的 Unicode 字符串。- 字符串类型在 Go 中有其独特的特性和操作方式,它以字节数组(
[]byte)形式存储,并且具备编码、切片等强大的特性。 - 声明字符串后,字符串默认值是
""(空字符串)。 - string 是值类型,不是引用类型。
- 特点:
- 数据不可变:string 是值类型,不是引用类型
- 默认值可用:声明后默认值为
"" - 支持
+或者+=运算:可以使用+或者+=连接运算符连接两个字符串 - 支持
len()获取长度:可以使用len()函数获取字符串的长度 - 支持
for-range遍历:可以使用for-range语法遍历字符串中的每个字符 - 支持
[]切片操作:可以使用[]操作符获取字符串中的单个字节或字符 - 支持
==、!=、<、>、<=、>=比较运算:可以使用比较运算符比较两个字符串 - 支持多行定义:可以使用反引号
` `定义多行字符串
基本定义与使用
Go 中的字符串可以用双引号 "" 或反引号 ` ` 包围:
package main
import "fmt"
func main() {
var s1 string = "Hello, Go!" // 使用双引号定义字符串
var s2 string = `This is a raw string literal.` // 使用反引号定义原始字符串
fmt.Println(s1) // 输出:Hello, Go!
fmt.Println(s2) // 输出:This is a raw string literal.
}字符串类型的特点:
- 不可变性:字符串一旦创建就不能修改,每次对字符串进行操作都会返回一个新的字符串。
- 存储方式:字符串在底层是一个字节数组,支持通过索引访问单个字节,但不能直接修改。
字符串的声明与初始化
字符串的声明方式有多种,可以使用 var 关键字、短变量声明 :=、或者直接赋值。
var str1 string = "Hello, World!" // 使用 var 关键字
str2 := "Go Programming" // 使用 := 短变量声明
str3 := "" // 声明一个空字符串字符串的长度与遍历
可以使用 len() 函数来获取字符串的长度。注意,len() 返回的是字符串中字节的数量而不是字符的数量。
str := "Hello, 世界"
fmt.Println(len(str)) // 输出:13(因为 '世' 和 '界' 是 3 个字节)
// 遍历字符串时可以使用 for-range 语法
for i, ch := range str {
fmt.Printf("Index: %d, Character: %c\n", i, ch)
}在 for-range 循环中,每次迭代都会返回索引 i 和 Unicode 码点(rune)形式的字符 ch,而不是字节。
字符串的切片操作
字符串可以像数组一样进行切片操作,切片时需要指定起始索引和结束索引。注意:字符串切片返回的依然是字符串。
str := "Hello, Go!"
fmt.Println(str[0:5]) // 输出:Hello
fmt.Println(str[7:]) // 输出:Go!注意
切片操作基于字节而非字符,这意味着对于包含多字节字符(如中文、特殊符号等)的字符串,直接使用切片可能导致乱码。
字符串的连接
Go 提供了多种字符串连接方式。最常用的是使用 + 操作符,也可以使用 fmt.Sprintf 或 strings.Join。
str1 := "Hello"
str2 := "Go"
result := str1 + ", " + str2 + "!" // 使用 + 操作符连接字符串
fmt.Println(result) // 输出:Hello, Go!其他连接方式:
fmt.Sprintf格式化字符串:gostr1 := "Hello" str2 := "Go" result := fmt.Sprintf("%s, %s!", str1, str2) fmt.Println(result) // 输出:Hello, Go!strings.Join连接字符串切片:goimport "strings" strSlice := []string{"Hello", "Go", "Language"} result := strings.Join(strSlice, " ") // 使用空格连接切片中的字符串 fmt.Println(result) // 输出:Hello Go Language
字符串比较
Go 中的字符串比较可以直接使用 ==、!=、<、> 等运算符。比较时按字典序进行。
str1 := "Hello"
str2 := "World"
fmt.Println(str1 == str2) // 输出:false
fmt.Println(str1 < str2) // 输出:true(因为 "Hello" 在字典序中小于 "World")字符串包含与查找
可以使用 strings 包提供的函数来进行包含、查找、前缀和后缀匹配等操作。
import "strings"
str := "Hello, Go!"
fmt.Println(strings.Contains(str, "Go")) // 检查是否包含子字符串 "Go",输出:true
fmt.Println(strings.HasPrefix(str, "Hello")) // 检查前缀是否为 "Hello",输出:true
fmt.Println(strings.HasSuffix(str, "!")) // 检查后缀是否为 "!",输出:true
fmt.Println(strings.Index(str, "Go")) // 查找 "Go" 的索引位置,输出:7字符串替换
可以使用 strings.Replace 进行字符串替换。
import "strings"
str := "Hello, Go! Go!"
newStr := strings.Replace(str, "Go", "Golang", 1) // 只替换第一个 "Go"
fmt.Println(newStr) // 输出:Hello, Golang! Go!
newStr = strings.Replace(str, "Go", "Golang", -1) // 替换所有 "Go"
fmt.Println(newStr) // 输出:Hello, Golang! Golang!字符串分割
可以使用 strings.Split 分割字符串为一个切片:
import "strings"
str := "Go,Python,Java"
splitStr := strings.Split(str, ",") // 按逗号分割字符串
fmt.Println(splitStr) // 输出:[Go Python Java]字符串转换
字节数组与字符串的转换:
[]byte(str)将字符串转换为字节切片。string([]byte)将字节切片转换为字符串。gostr := "Hello" bytes := []byte(str) // 字符串转为字节数组 fmt.Println(bytes) // 输出:[72 101 108 108 111] newStr := string(bytes) // 字节数组转为字符串 fmt.Println(newStr) // 输出:Hello
大小写转换:
goimport "strings" str := "Hello, Go!" fmt.Println(strings.ToUpper(str)) // 转换为大写:HELLO, GO! fmt.Println(strings.ToLower(str)) // 转换为小写:hello, go!
多行字符串与原始字符串
使用反引号(`)定义多行字符串或原始字符串。
str := `This is a raw string literal.
It can span multiple lines without escaping characters like \n or \t.
`
fmt.Println(str) // 输出:This is a raw string literal. It can span multiple lines without escaping characters like \n or \t.反引号定义的字符串可以包含特殊字符而不需要转义,例如 \n、\t 等。
字符串与 rune
在 Go 中,字符串是 UTF-8 编码的字节序列。如果需要处理 Unicode 字符,可以使用 rune 类型(表示 Unicode 码点)。
str := "Hello, 世界"
runes := []rune(str) // 将字符串转换为 rune 切片
for _, r := range runes {
fmt.Printf("%c ", r) // 逐个打印 Unicode 字符
}
// 输出:H e l l o , 世 界字符串的性能优化
当需要对字符串进行大量拼接时,使用 strings.Builder 会更高效:
import "strings"
var builder strings.Builder
builder.WriteString("Hello")
builder.WriteString(", ")
builder.WriteString("Go!")
result := builder.String()
fmt.Println(result) // 输出:Hello, Go!使用 strings.Builder 可以避免频繁的字符串拷贝,从而提升性能。