Skip to content

字符串操作 (strings)

strings 包提供了丰富的字符串操作函数,是处理文本数据的基础工具。

📋 学习目标

  • 掌握字符串的查找和匹配
  • 学会字符串的替换和修改
  • 理解字符串的分割和拼接
  • 掌握字符串的修剪和格式化
  • 了解字符串构建器的高效使用

🔍 字符串查找

基本查找

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "Hello, World"

	// 检查是否包含子串
	contains := strings.Contains(str, "World")
	fmt.Printf("包含 'World': %t\n", contains) // true

	// 查找子串位置
	index := strings.Index(str, "World")
	fmt.Printf("'World' 的位置: %d\n", index) // 7

	// 查找最后出现的位置
	lastIndex := strings.LastIndex(str, "o")
	fmt.Printf("'o' 最后出现的位置: %d\n", lastIndex) // 8

	// 查找任意字符
	anyIndex := strings.IndexAny(str, "aeiou")
	fmt.Printf("第一个元音字母位置: %d\n", anyIndex) // 1 (e)

	// 统计出现次数
	count := strings.Count(str, "l")
	fmt.Printf("'l' 出现次数: %d\n", count) // 3
}

前缀和后缀

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "Hello, World"

	// 检查前缀
	hasPrefix := strings.HasPrefix(str, "Hello")
	fmt.Printf("以 'Hello' 开头: %t\n", hasPrefix) // true

	// 检查后缀
	hasSuffix := strings.HasSuffix(str, "World")
	fmt.Printf("以 'World' 结尾: %t\n", hasSuffix) // true
}

🔄 字符串替换

基本替换

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "Hello, World, World"

	// 替换第一个匹配
	newStr1 := strings.Replace(str, "World", "Go", 1)
	fmt.Printf("替换第一个: %s\n", newStr1) // Hello, Go, World

	// 替换所有匹配
	newStr2 := strings.ReplaceAll(str, "World", "Go")
	fmt.Printf("替换所有: %s\n", newStr2) // Hello, Go, Go

	// 替换指定次数
	newStr3 := strings.Replace(str, "World", "Go", 2)
	fmt.Printf("替换2次: %s\n", newStr3) // Hello, Go, Go
}

大小写转换

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "Hello, World"

	// 转大写
	upper := strings.ToUpper(str)
	fmt.Printf("大写: %s\n", upper) // HELLO, WORLD

	// 转小写
	lower := strings.ToLower(str)
	fmt.Printf("小写: %s\n", lower) // hello, world

	// 首字母大写(已废弃,建议使用其他方法)
	title := strings.Title(str)
	fmt.Printf("标题格式: %s\n", title) // Hello, World

	// 每个单词首字母大写
	// 注意:Go 1.18+ 推荐使用 cases 包
}

✂️ 字符串修剪

去除空白字符

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "  Hello, World  "

	// 去除两端空白
	trimmed := strings.TrimSpace(str)
	fmt.Printf("去除空白: '%s'\n", trimmed) // 'Hello, World'

	// 去除左侧空白
	trimLeft := strings.TrimLeft(str, " ")
	fmt.Printf("去除左侧空白: '%s'\n", trimLeft)

	// 去除右侧空白
	trimRight := strings.TrimRight(str, " ")
	fmt.Printf("去除右侧空白: '%s'\n", trimRight)

	// 去除指定字符
	trimmed2 := strings.Trim("!!!Hello!!!", "!")
	fmt.Printf("去除 '!': %s\n", trimmed2) // Hello
}

去除前缀和后缀

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "Hello, World"

	// 去除前缀
	withoutPrefix := strings.TrimPrefix(str, "Hello, ")
	fmt.Printf("去除前缀: %s\n", withoutPrefix) // World

	// 去除后缀
	withoutSuffix := strings.TrimSuffix(str, ", World")
	fmt.Printf("去除后缀: %s\n", withoutSuffix) // Hello
}

🔪 字符串分割

基本分割

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "apple,banana,orange,grape"

	// 按分隔符分割
	parts := strings.Split(str, ",")
	fmt.Printf("分割结果: %v\n", parts) // [apple banana orange grape]

	// 限制分割次数
	parts2 := strings.SplitN(str, ",", 2)
	fmt.Printf("分割2次: %v\n", parts2) // [apple banana,orange,grape]

	// 按空白字符分割
	words := strings.Fields("  hello   world  go  ")
	fmt.Printf("按空白分割: %v\n", words) // [hello world go]
}

高级分割

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "a,b,c,d"

	// 分割后保留分隔符
	parts := strings.SplitAfter(str, ",")
	fmt.Printf("保留分隔符: %v\n", parts) // [a, b, c, d]

	// 限制分割次数并保留分隔符
	parts2 := strings.SplitAfterN(str, ",", 2)
	fmt.Printf("保留分隔符分割2次: %v\n", parts2) // [a, b,c,d]
}

🔗 字符串拼接

基本拼接

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	// 使用 + 运算符(少量拼接)
	str1 := "Hello" + " " + "World"
	fmt.Printf("拼接结果: %s\n", str1)

	// 使用 Join(固定分隔符)
	parts := []string{"apple", "banana", "orange"}
	str2 := strings.Join(parts, ", ")
	fmt.Printf("Join 结果: %s\n", str2) // apple, banana, orange
}

使用 Builder(高效拼接)

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	var builder strings.Builder

	// 追加字符串
	builder.WriteString("Hello")
	builder.WriteString(" ")
	builder.WriteString("World")

	// 追加字节
	builder.WriteByte('!')

	// 追加 rune
	builder.WriteRune('🎉')

	// 获取结果
	result := builder.String()
	fmt.Printf("Builder 结果: %s\n", result) // Hello World!🎉

	// 预分配容量(性能优化)
	builder2 := strings.Builder{}
	builder2.Grow(100) // 预分配100字节
	builder2.WriteString("Pre-allocated")
	fmt.Printf("预分配结果: %s\n", builder2.String())
}

🔤 字符串比较

基本比较

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str1 := "Hello"
	str2 := "hello"

	// 区分大小写比较
	equal := str1 == str2
	fmt.Printf("相等: %t\n", equal) // false

	// 忽略大小写比较
	equalFold := strings.EqualFold(str1, str2)
	fmt.Printf("忽略大小写相等: %t\n", equalFold) // true

	// 比较大小(字典序)
	compare := strings.Compare(str1, str2)
	fmt.Printf("比较结果: %d\n", compare) // -1 (str1 < str2)
}

📊 字符串映射和转换

Map 函数

go
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	str := "Hello World 123"

	// 将字符串中的每个字符映射
	mapped := strings.Map(func(r rune) rune {
		if unicode.IsLetter(r) {
			return unicode.ToUpper(r)
		}
		return r
	}, str)
	fmt.Printf("映射结果: %s\n", mapped) // HELLO WORLD 123
}

Repeat 函数

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	// 重复字符串
	repeated := strings.Repeat("Go ", 3)
	fmt.Printf("重复结果: %s\n", repeated) // Go Go Go
}

🎯 实用工具函数

字符串转换

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	// 字符串转切片
	str := "Hello"
	bytes := []byte(str)
	runes := []rune(str)

	fmt.Printf("字节切片: %v\n", bytes)
	fmt.Printf("Rune 切片: %v\n", runes)

	// 切片转字符串
	str2 := string(bytes)
	str3 := string(runes)
	fmt.Printf("字节转字符串: %s\n", str2)
	fmt.Printf("Rune 转字符串: %s\n", str3)
}

字符串验证

go
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	str := "Hello123"

	// 检查是否只包含字母
	hasOnlyLetters := true
	for _, r := range str {
		if !unicode.IsLetter(r) {
			hasOnlyLetters = false
			break
		}
	}
	fmt.Printf("只包含字母: %t\n", hasOnlyLetters) // false

	// 检查是否为空
	isEmpty := strings.TrimSpace(str) == ""
	fmt.Printf("是否为空: %t\n", isEmpty) // false
}

🏃‍♂️ 实践应用

文本处理工具

go
package main

import (
	"fmt"
	"strings"
)

// 单词计数
func wordCount(text string) map[string]int {
	words := strings.Fields(strings.ToLower(text))
	count := make(map[string]int)
	for _, word := range words {
		word = strings.Trim(word, ".,!?;:")
		count[word]++
	}
	return count
}

// 清理文本
func cleanText(text string) string {
	// 去除多余空白
	text = strings.TrimSpace(text)
	// 替换多个空白为单个
	words := strings.Fields(text)
	return strings.Join(words, " ")
}

func main() {
	text := "  Hello   World  Hello  Go  "

	// 单词计数
	counts := wordCount(text)
	fmt.Printf("单词计数: %v\n", counts)

	// 清理文本
	cleaned := cleanText(text)
	fmt.Printf("清理后: '%s'\n", cleaned)
}

URL 路径处理

go
package main

import (
	"fmt"
	"strings"
)

func normalizePath(path string) string {
	// 去除前后斜杠
	path = strings.Trim(path, "/")
	// 确保以 / 开头
	if !strings.HasPrefix(path, "/") {
		path = "/" + path
	}
	// 去除重复斜杠
	parts := strings.Split(path, "/")
	var cleanParts []string
	for _, part := range parts {
		if part != "" {
			cleanParts = append(cleanParts, part)
		}
	}
	return "/" + strings.Join(cleanParts, "/")
}

func main() {
	paths := []string{
		"//api//users//",
		"/api/users",
		"api/users/",
	}

	for _, path := range paths {
		normalized := normalizePath(path)
		fmt.Printf("原始: %s -> 规范化: %s\n", path, normalized)
	}
}

⚠️ 注意事项

1. 性能考虑

go
// ❌ 避免:大量字符串拼接使用 +
var result string
for i := 0; i < 1000; i++ {
	result += "a" // 每次都会创建新字符串
}

// ✅ 正确:使用 Builder
var builder strings.Builder
for i := 0; i < 1000; i++ {
	builder.WriteString("a")
}
result := builder.String()

2. Unicode 处理

go
// 注意:strings 包按字节操作,处理 Unicode 时要注意
str := "你好"
fmt.Println(len(str)) // 6 (字节数,不是字符数)

// 处理 Unicode 字符时使用 []rune
runes := []rune(str)
fmt.Println(len(runes)) // 2 (字符数)

3. 字符串不可变性

go
// Go 中字符串是不可变的
str := "Hello"
// str[0] = 'h' // 编译错误

// 需要修改时创建新字符串
newStr := "h" + str[1:]

📚 扩展阅读

⏭️ 下一章节

数学运算 (math) → 学习使用数学函数进行数值计算


💡 提示: strings 包是处理文本数据的基础工具,掌握它对于处理用户输入、配置文件、日志等文本数据非常重要!

基于 VitePress 构建