strings包为Go语言的字符串处理提供了丰富的方法,可以大致分为以下几类:字符串查找与是否包含、字符串切割与连接、字符串修剪、字符串替换与重复、字符串大小写转换与映射。

本文将聚焦于字符串查找、切割与连接这两部分的核心方法及其实现原理。
字符串查找与是否包含
我们先通过基础示例了解Contains和Index系列函数的用法。
str := "夏天夏天悄悄过去留下小秘密~"
log.Println(strings.Contains(str, "小"))
log.Println(strings.ContainsAny(str, "冬天"))
log.Println(strings.ContainsFunc(str, func(r rune) bool {
return r == '~'
}))
log.Println(strings.ContainsRune(str, '小'))
log.Println(strings.Index(str, "天"))
log.Println(strings.LastIndex(str, "天"))
输出结果:
2025/12/18 20:24:33 true
2025/12/18 20:24:33 true
2025/12/18 20:24:33 true
2025/12/18 20:24:33 true
2025/12/18 20:24:33 3
2025/12/18 20:24:33 9
Contains 系列函数
Contains系列函数用于判断字符串中是否包含特定的字符或子串。
Contains(s, substr string) bool: 判断字符串s中是否包含子串substr。
ContainsAny(s, chars string) bool: 判断字符串s中是否包含chars中的任意一个Unicode字符。
ContainsRune(s string, r rune) bool: 判断字符串s中是否包含特定的Unicode码点r。
ContainsFunc(s string, f func(rune) bool) bool: 判断字符串s中是否存在满足自定义函数f条件的字符。
查看源码可以发现,这一系列函数本质上都是通过对应的Index系列函数来实现的,仅判断返回值是否大于等于0。
func Contains(s, substr string) bool {
return Index(s, substr) >= 0
}
func ContainsAny(s, chars string) bool {
return IndexAny(s, chars) >= 0
}
func ContainsRune(s string, r rune) bool {
return IndexRune(s, r) >= 0
}
func ContainsFunc(s string, f func(rune) bool) bool {
return IndexFunc(s, f) >= 0
}
Index 系列函数
Index系列函数用于返回字符或子串在字符串中首次或最后一次出现的位置索引。
Index(s, substr string) int: 返回子串substr在s中第一次出现的索引,不存在则返回-1。
LastIndex(s, substr string) int: 返回子串substr在s中最后一次出现的索引。
- 其他函数如
IndexRune, IndexAny, LastIndexAny等作用类似,分别针对rune、字符集等进行查找。
其核心Index函数的实现依赖于Go内部非导出的轻量级包stringslite。
// Index returns the index of the first instance of substr in s, or -1 if substr is not present in s.
func Index(s, substr string) int {
return stringslite.Index(s, substr)
}
字符串切割与连接
字符串的切割主要由Split和Fields方法完成,而Join方法则用于拼接字符串切片。
Split 系列函数
Split函数用于根据指定的分隔符将字符串切割成子串切片。
str := "A,B,C,D"
arr1 := strings.Split(str, ",")
arr2 := strings.SplitN(str, ",", 3)
arr3 := strings.SplitAfter(str, ",")
log.Println(arr1, len(arr1), arr2, len(arr2))
log.Println(arr3, len(arr3))
输出:
2025/12/18 20:42:51 [A B C D] 4 [A B C,D] 3
2025/12/18 20:42:52 [A, B, C, D] 4
根据官方注释,Split(s, sep string) []string的行为如下:
- 将字符串
s按分隔符sep拆分为所有子串。
- 如果
s中不包含sep且sep非空,则返回长度为1的切片(仅包含s)。
- 如果
sep为空字符串,则在每个UTF-8序列后拆分。
- 如果
s和sep均为空,则返回空切片。
其实现依赖于内部函数genSplit,该函数控制是否保留分隔符以及返回子串的数量。Split、SplitAfter、SplitN、SplitAfterN均由此函数实现。
func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) }
SplitN(s, sep string, n int) []string: 控制返回子串的数量n(n>0: 最多n个;n==0: 返回nil;n<0: 返回所有)。
SplitAfter(s, sep string) []string: 在每个sep实例之后进行切分,结果中会保留分隔符。
Fields 系列函数
Fields函数用于按照一个或多个连续的空白字符(由unicode.IsSpace定义)来分割字符串。
str := "A B C D"
arr1 := strings.Fields(str)
log.Println(arr1, len(arr1))
输出:
2025/12/18 21:07:38 [A B C D] 4
Fields(s string) []string的用途是清空连续空白字符,将s切分为子串切片。如果s仅包含空白字符,则返回空切片。FieldsFunc功能类似,但允许自定义分割判断函数。
其实现包含针对纯ASCII字符串的快速路径优化,当检测到非ASCII字符时,会回退到使用更通用的FieldsFunc(s, unicode.IsSpace)。
Join 函数
Join函数用于将字符串切片连接成单个字符串,元素间插入指定的分隔符。
str := []string{"A", "B", "C", "D"}
j1 := strings.Join(str, "-")
log.Println(j1)
输出:
2025/12/18 21:19:06 A-B-C-D
Join(elems []string, sep string) string的实现高效且严谨:
- 处理边界情况:切片为空时返回空字符串,只有一个元素时直接返回该元素。
- 计算最终字符串长度:总和为所有元素长度加上
(元素数量-1) 个分隔符的长度。这里包含了整数溢出检查。
- 使用
strings.Builder进行高效构建:先调用Grow方法预分配足够内存以避免拼接过程中的多次扩容,这对于Golang的高性能字符串处理至关重要。
- 遍历切片,依次写入元素和分隔符(第一个元素前不写分隔符)。
func Join(elems []string, sep string) string {
switch len(elems) {
case 0:
return ""
case 1:
return elems[0]
}
// ... 长度计算与溢出检查 ...
var b Builder
b.Grow(n) // 预分配
b.WriteString(elems[0])
for _, s := range elems[1:] {
b.WriteString(sep)
b.WriteString(s)
}
return b.String()
}
字符串的修剪(Trim)、替换(Replace)、大小写转换等操作同样设计精妙,我们将在后续内容中结合网络与系统中常见的编码处理场景继续分析。