strings库
func EqualFold
go
func EqualFold(s, t string) bool
判断两个utf-8编码字符串(将unicode大写、小写、标题三种格式字符视为相同)是否相同。
go
func main() {
fmt.Println(strings.EqualFold("hello", "hello")) //true
fmt.Println(strings.EqualFold("hello", "HELLO")) //true
fmt.Println(strings.EqualFold("hello", "Hello")) //true
}
func HasPrefix
go
func HasPrefix(s, prefix string) bool
判断s是否有前缀字符串prefix。
go
func main() {
fmt.Println(strings.HasPrefix("golang", "go")) // true
fmt.Println(strings.HasPrefix("golang", "lang")) // false
}
func HasSuffix
go
func HasSuffix(s, suffix string) bool
判断s是否有后缀字符串suffix。
go
func main() {
fmt.Println(strings.HasSuffix("hello.txt", ".txt")) // true
fmt.Println(strings.HasSuffix("hello.txt", ".jpg")) // false
}
func Contains
go
func Contains(s, substr string) bool
判断字符串s是否包含子串subs
go
func main() {
fmt.Println(strings.Contains("hello world", "world")) // true
fmt.Println(strings.Contains("golang", "java")) // false
}
func ContainsRune
go
func ContainsRune(s string, r rune) bool
判断字符串s是否包含utf-8码值r。
go
func main() {
fmt.Println(strings.ContainsRune("你好,世界", '界')) // true
fmt.Println(strings.ContainsRune("hello", '你')) // false
fmt.Println(strings.ContainsRune("hello", 'h')) // true
}
//这个是适用于单个Unicode字符检查,而不是子串
//如果输入多个字符的话,报这个错:Too many characters in the rune literal
func ContainsAny
go
func ContainsAny(s, chars string) bool
判断字符串s是否包含字符串chars中的任一字符。
go
func main() {
fmt.Println(strings.ContainsAny("hello", "aeiou")) // true (包含 'e'、'o')
fmt.Println(strings.ContainsAny("golang", "xyz")) // false
}
func Count
go
func Count(s, sep string) int
返回字符串s中有几个不重复的sep子串。
go
func main() {
fmt.Println(strings.Count("banana", "a")) // 3
fmt.Println(strings.Count("hello", "l")) // 2
fmt.Println(strings.Count("golang", "go")) // 1
fmt.Println(strings.Count("aaaa", "")) //猜一下这个
}
func Index
go
func Index(s, sep string) int
子串sep在字符串s中第一次出现的位置,不存在则返回-1。
go
func main() {
s := "hello world"
fmt.Println(strings.Index(s, "world")) // 6
fmt.Println(strings.Index(s, "go")) // -1 (找不到返回 -1)
}
func IndexByte
go
func IndexByte(s string, c byte) int
字符c在s中第一次出现的位置,不存在则返回-1。
go
func main() {
s := "hello"
fmt.Println(strings.IndexByte(s, 'e')) // 1
fmt.Println(strings.IndexByte(s, 'x')) // -1
}
IndexByte适合查找**ASCII** 字符,因为
byte是单字节,无法直接表示多字节的 UTF-8 字符(例如中文)。
如果你要查找英文或单字节字符 ,可以用这个函数,性能会比 IndexRune
略好。
func IndexRune
go
func IndexRune(s string, r rune) int
unicode码值r在s中第一次出现的位置,不存在则返回-1。
go
func main() {
s := "你好,世界"
fmt.Println(strings.IndexRune(s, '世')) // 9
fmt.Println(strings.IndexRune(s, '界')) // 12
fmt.Println(strings.IndexRune(s, '你')) // 0
fmt.Println(strings.IndexRune(s, 'x')) // -1
}
对于多字节字符(如中文),IndexRune
可以正确识别并定位索引。
注意索引依旧是以字节为单位计算的。例如 "你好":
'你'
占用 3 个字节,索引从 0~2;'好'
索引从 3~5。
所以'好'
的开始索引是 3。
func IndexAny
go
func IndexAny(s, chars string) int
字符串chars中的任一utf-8码值在s中第一次出现的位置,如果不存在或者chars为空字符串则返回-1。
go
func main() {
s := "hello"
fmt.Println(strings.IndexAny(s, "jker")) // 1 (因为 'e' 出现在索引 1)
fmt.Println(strings.IndexAny(s, "xyz")) // -1 (找不到)
//猜一下下面的
fmt.Println(strings.IndexAny(s, "loo"))
fmt.Println(strings.IndexAny(s, "ollo"))
fmt.Println(strings.IndexAny(s, "olloe"))
}
一次性查找多个可能的字符,只要匹配到其中一个字符,就返回首次出现的索引。
func IndexFunc
go
func IndexFunc(s string, f func(rune) bool) int
在字符串 s
中,从左到右遍历,每次取出一个 Unicode 字符 r
并调用 f(r)
判断是否为 true ,如果是,则返回该字符在字符串中的索引。若遍历完都不为 true
,返回 -1。
go
func main() {
s := "123abc"
// 找到第一个字母的位置
index := strings.IndexFunc(s, func(r rune) bool {
return unicode.IsLetter(r)
})
fmt.Println(index) // 3 ("a" 的位置)
}
f
是一个判断函数,通常会使用到 unicode
包的判断方法(如 unicode.IsLetter
、unicode.IsDigit
、unicode.IsSpace
等)。
适合自定义复杂的匹配条件。
func LastIndex
go
func LastIndex(s, sep string) int
子串sep在字符串s中最后一次出现的位置,不存在则返回-1。
go
func main() {
s := "hello world world"
fmt.Println(strings.LastIndex(s, "world")) // 12
fmt.Println(strings.LastIndex(s, "go")) // -1
}
LastIndex
用于反向搜索子串的出现位置。
例如文件路径处理时,需要找最后一个斜杠 /
的位置,可以用 LastIndex
来提取文件名等。
func LastIndexAny
go
func LastIndexAny(s, chars string) int
在字符串 s
中查找 chars
中任意一个字符最后一次出现的位置,找不到返回 -1。
go
func main() {
s := "hello world"
fmt.Println(strings.LastIndexAny(s, "o")) //'0' 7
//猜一下
fmt.Println(strings.LastIndexAny(s, "hello"))
}
func LastIndexFunc
go
func LastIndexFunc(s string, f func(rune) bool) int
从右往左遍历字符串 s
,每次取出一个 Unicode 字符 r
,调用 f(r)
判断是否为 true
,
若是,则返回该字符在字符串中的索引,否则 -1
go
func main() {
s := "GoLang 123"
// 找到最后一个字母
index := strings.LastIndexFunc(s, func(r rune) bool {
return unicode.IsLetter(r)
})
fmt.Println(index) // 5 ('g' 的索引)
}
func Title
go
func Title(s string) string
返回字符串 s
的拷贝,其中每个"单词"的首字母都被转换为 Title Case(类似首字母大写)。
- 注意:"单词" 的定义基于 Unicode 标准,会按照空格或非字母边界来拆分。
go
func main() {
s := "her royal highness"
fmt.Println(strings.Title(s)) // "Her Royal Highness"
}
func ToLower
go
func ToLower(s string) string
返回将所有字母都转为对应的小写版本的拷贝。
go
func main() {
fmt.Println(strings.ToLower("Hello WORLD!")) // "hello world!"
}
func ToUpper
go
func ToUpper(s string) string
返回将所有字母都转为对应的大写版本的拷贝。
go
func main() {
fmt.Println(strings.ToUpper("Hello WORLD!")) // "HELLO WORLD!"
}
func ToTitle
go
func ToTitle(s string) string
返回将所有字母都转为对应的标题版本的拷贝。
go
func main() {
fmt.Println(strings.ToTitle("loud noises")) //LOUD NOISES
s := "lj dz dž hello"
fmt.Println(strings.ToUpper(s)) // "LJ DZ DŽ HELLO"
fmt.Println(strings.ToTitle(s)) // "LJ Dz Dž HELLO"
}
区别于 strings.ToUpper
:
ToTitle
对普通字母的效果等同于ToUpper
- 但对于某些特殊的 Unicode 字母(如
lj
、dž
),ToTitle
会转换成Titlecase
而不是Uppercase
func Repeat
go
func Repeat(s string, count int) string
返回一个新字符串,由 s
重复 count
次拼接而成。
go
func main() {
fmt.Println(strings.Repeat("ha", 3)) // "hahaha"
}
func Replace
go
func Replace(s, old, new string, n int) string
在字符串 s
中,把 old
替换成 new
,共替换 n
次,返回新字符串。若 n
< 0,则替换所有出现。
go
package main
import (
"fmt"
"strings"
)
func main() {
s := "hello world world"
fmt.Println(strings.Replace(s, "world", "Go", 1)) // "hello Go world"
fmt.Println(strings.Replace(s, "world", "Go", -1)) // "hello Go Go"
//ReplaceAll(s, old, new string) string
fmt.Println(strings.ReplaceAll(s, "world", "Go")) //类似于 strings.Replace(s, "world", "Go", -1)
}
func Map
go
func Map(mapping func(rune) rune, s string) string
对字符串 s
中的每个 Unicode 字符 r
调用 mapping(r)
,返回映射后的字符,并组成新字符串。
若 mapping
返回 -1
,则会丢弃该字符。
go
func main() {
s := "Hello 123"
// 将所有数字去掉
result := strings.Map(func(r rune) rune {
if unicode.IsDigit(r) {
return -1 // -1 表示丢弃这个字符
}
return r
}, s)
fmt.Println(result) // "Hello "
//大小写转化
result = strings.Map(func(r rune) rune {
return unicode.ToUpper(r)
}, s)
fmt.Println(result) //HELLO 123
str := "Go@lang! is #awesome$"
// 替换 @, !, #, $ 为 *
result = strings.Map(func(r rune) rune {
switch r {
case '@', '!', '#', '$':
return '*'
default:
return r
}
}, str)
fmt.Println(result) // "Go*lang* is *awesome*"
}
Map
适合对字符串做逐字符的自定义转换或过滤。
func Trim
go
func Trim(s string, cutset string) string
用于去除字符串两端的指定字符集 (cutset
)中的字符。
go
func main() {
s := " !hello world! "
cutset := " !"
// 去除两端的空格和感叹号
result := strings.Trim(s, cutset)
fmt.Println(result) // "hello world"
}
func TrimSpace
go
func TrimSpace(s string) string
去除字符串 s
开头和结尾的空白字符(包括空格、制表符、换行等)。
go
func main() {
s := " Hello Golang \n "
fmt.Println(strings.TrimSpace(s)) // "Hello Golang"
}
func TrimFunc
go
func TrimFunc(s string, f func(rune) bool) string
根据自定义的判定函数(函数类型为 func(rune) bool
)去除字符串两端的字符。
go
func main() {
s := "123!Hello, Go!?!456"
// 定义判定函数:如果字符不是字母,则返回 true,表示该字符需要被移除
trimFunc := func(r rune) bool {
return !unicode.IsLetter(r)
}
// 使用 TrimFunc 去除两端非字母字符
result := strings.TrimFunc(s, trimFunc)
fmt.Println(result) // 输出 "Hello, Go!?"
//去除两端的的数字
trimFunc = func(r rune) bool {
return unicode.IsDigit(r)
}
result = strings.TrimFunc(s, trimFunc)
fmt.Println(result) // 输出 "!Hello, Go!?!"
}
func TrimLeft
go
func TrimLeft(s string, cutset string) string
从字符串 左侧 (即开头)开始移除所有出现在 cutset
中的字符,直到遇到第一个不在 cutset
中的字符为止。
仅对字符串开头部分进行处理,中间和结尾的字符不会受影响。
go
func main() {
s := "!!!Hello, World!!!"
cutset := "!"
// 去除左侧所有感叹号
leftTrimmed := strings.TrimLeft(s, cutset)
fmt.Println(leftTrimmed) // 输出: "Hello, World!!!"
}
func TrimLeftFunc
go
func TrimLeftFunc(s string, f func(rune) bool) string
从左侧 开始,移除连续满足 f(rune) == true
的字符,直到遇到不满足的字符后停止。
go
func main() {
s := " Hello 123"
// 移除左侧空白
result := strings.TrimLeftFunc(s, unicode.IsSpace)
fmt.Println(result) // "Hello 123"
}
func TrimPrefix
go
func TrimPrefix(s, prefix string) string
若字符串 s
以 prefix
开头,则去除该前缀并返回剩余部分;否则返回 s
本身。
go
func main() {
s := "HelloWorld"
fmt.Println(strings.TrimPrefix(s, "Hello")) // "World"
fmt.Println(strings.TrimPrefix(s, "Go")) // "HelloWorld" (无变化)
}
func TrimRight
go
func TrimRight(s string, cutset string) string
TrimRight
从字符串 右侧 (即结尾)开始移除所有出现在 cutset
中的字符,直到遇到第一个不在 cutset
中的字符为止。
仅对字符串末尾部分进行处理,左侧和中间的字符不会受影响。
go
func main() {
s := "!!!Hello, World!!!"
cutset := "!"
// 去除右侧所有感叹号
rightTrimmed := strings.TrimRight(s, cutset)
fmt.Println(rightTrimmed) // 输出: "!!!Hello, World"
}
func TrimRightFunc
go
func TrimRightFunc(s string, f func(rune) bool) string
从右侧 开始,移除连续满足 f(rune) == true
的字符,直到遇到不满足的字符后停止。
go
func main() {
s := "Hello 123 "
result := strings.TrimRightFunc(s, unicode.IsSpace)
fmt.Println(result) // "Hello 123"
}
func TrimSuffix
go
func TrimSuffix(s, suffix string) string
若字符串 s
以 suffix
结尾,则去除该后缀并返回剩余部分;否则返回 s
本身。
go
func main() {
s := "HelloWorld"
fmt.Println(strings.TrimSuffix(s, "World")) // "Hello"
fmt.Println(strings.TrimSuffix(s, "Go")) // "HelloWorld"
}
func Fields
go
func Fields(s string) []string
strings.Fields
根据 Unicode 空白字符将字符串分割成多个字段。空白字符包括空格、制表符、换行符等,函数会把连续的空白字符看作一个分隔符。
go
func main() {
s := " hello\tworld\n Go 语言 "
fields := strings.Fields(s)
fmt.Println(fields) // 输出: ["hello" "world" "Go" "语言"]
}
func FieldsFunc
go
func TrimSuffix(s, suffix string) string
strings.FieldsFunc
根据用户提供的判定函数来分割字符串。这个函数接受一个 rune
参数,并返回 true
或 false
。当判定函数返回 true
时,该字符被视为分隔符。
go
// 定义一个函数,将所有非字母和非汉字的字符作为分隔符
func isNotLetter(r rune) bool {
return !unicode.IsLetter(r) && !unicode.Is(unicode.Han, r)
}
func main() {
s := "hello,world!欢迎来到-Go语言."
// 根据自定义规则分割字符串
fields := strings.FieldsFunc(s, isNotLetter)
fmt.Println(fields) // 输出: ["hello" "world" "欢迎" "来到" "Go语言"]
}
func Split
go
func Split(s, sep string) []string
按分隔符 sep
拆分字符串 s
,返回 []string
。
- 若
sep
为空字符串""
,则将s
按单个字符拆分。 - 若
sep
在s
中不存在,则返回[s]
。
go
func main() {
s := "a,b,c"
fmt.Println(strings.Split(s, ",")) // ["a" "b" "c"]
fmt.Println(strings.Split(s, "")) //[a , b , c]
}
func SplitN
go
func SplitN(s, sep string, n int) []string
按分隔符 sep
拆分字符串 s
,最多拆分 n
个部分,返回 []string
。
- 如果
n
> 0,则最多返回n
个子串。 - 如果
n
< 0,则拆分所有可能的子串。
go
func main() {
s := "a,b,c,d"
fmt.Println(strings.SplitN(s, ",", 2)) // ["a" "b,c,d"]
fmt.Println(strings.SplitN(s, ",", -1)) //[a b c d]
}
func SplitAfter/func SplitAfterN
go
func SplitAfter(s, sep string) []string
func SplitAfterN(s, sep string, n int) []string
与 Split
/ SplitN
类似,但保留分隔符在拆分后的结果里。
go
func main() {
s := "a,b,c"
fmt.Println(strings.SplitAfter(s, ",")) // ["a," "b," "c"]
fmt.Println(strings.SplitAfterN(s, ",", 2)) // ["a," "b,c"]
}
func Join
go
func Join(a []string, sep string) string
将 []string
用分隔符 sep
拼接成一个字符串。
go
func main() {
words := []string{"Go", "is", "awesome"}
fmt.Println(strings.Join(words, " ")) // "Go is awesome"
}
适用于把切片合并成一行文本,比如生成 CSV 行、命令行参数等。
总结:常见字符串操作的思维导图
- 判断/搜索
Contains/ContainsRune/ContainsAny
:是否包含子串或字符HasPrefix/HasSuffix
:是否以某前缀/后缀开头或结尾Index/LastIndex
系列:查找子串或字符的第一次/最后一次出现位置Count
:统计子串出现次数EqualFold
:忽略大小写判断是否相等
- 大小写转换
ToLower/ToUpper/ToTitle
:将字符串全部转为小写/大写/标题形式Title
:对每个单词首字母做大写处理
- 替换/映射
Replace/ReplaceAll
:将子串替换为新字符串Map
:对每个字符做自定义转换,返回新字符串(可丢弃字符)
- 修剪(Trim)
Trim/TrimLeft/TrimRight
:去除指定字符集TrimSpace
:去除首尾空白字符TrimPrefix/TrimSuffix
:仅去除指定前缀/后缀TrimFunc
/TrimLeftFunc
/TrimRightFunc
:用自定义函数判断是否需要修剪
- 拆分/拼接
Split/SplitN/SplitAfter/SplitAfterN
:按分隔符拆分字符串Fields/FieldsFunc
:按空白或自定义条件拆分Join
:将[]string
用分隔符拼接为一个字符串
- 重复
Repeat
:将字符串重复n
次