[Go语言系列] 12. Go 语言字符串操作

Go语言系列知识快速查看入口

:point_down::point_down::point_down:

本章内容

1赞

12.1 字符串是否有某个前缀或后缀

函数签名

func HasPrefix(s, prefix string) bool
func HasSuffix(s, suffix string) bool

说明

HasPrefix - 判断字符串 s 中是否以 prefix 开始
HasSuffix - 判断字符串 s 中是否以 suffix 结尾
如果 prefix 或 suffix 为 "", 返回值总是true

示例

fmt.Println(strings.HasPrefix("Gopher", "Go"))
fmt.Println(strings.HasPrefix("Gopher", "C"))
fmt.Println(strings.HasPrefix("Gopher", ""))
fmt.Println(strings.HasSuffix("Amigo", "go"))
fmt.Println(strings.HasSuffix("Amigo", "Ami"))
fmt.Println(strings.HasSuffix("Amigo", ""))

输出

true
false
true
true
false
true
1赞

12.2 是否存在某个字符或子串

函数签名

func Contains(s, substr string) bool
func ContainsAny(s, chars string) bool

说明

Contains - 子串substr在字符串s中,返回true
ContainsAny - chars中任意一个字符(Unicode Code Point)在字符串s中,返回true

示例

fmt.Println(strings.Contains("team", "ea"))
fmt.Println(strings.Contains("team", "li"))
fmt.Println(strings.ContainsAny("team", "i"))
fmt.Println(strings.ContainsAny("failure", "u&i"))
fmt.Println(strings.ContainsAny("in failure", "s g"))
fmt.Println(strings.ContainsAny("foo", ""))
fmt.Println(strings.ContainsAny("", ""))

输出

true
false
false
true
true
false
false
1赞

12.3 字符或子串在字符串中出现的位置

(1)第一次出现的位置

函数签名

func Index(s, sep string) int
func IndexByte(s string, c byte) int
func IndexAny(s, chars string) int
func IndexFunc(s string, f func(rune) bool) int

说明

Index - 在 s 中查找 sep 的第一次出现,返回第一次出现的索引。
IndexByte - 在 s 中查找字节 c 的第一次出现,返回第一次出现的索引。
IndexAny - chars中任何一个 Unicode 代码点在 s 中首次出现的位置
IndexFunc - 查找字符 c 在 s 中第一次出现的位置,其中 c 满足 f(c) 返回true

示例

fmt.Println(strings.Index("hello world", "lo"))
fmt.Println(strings.IndexByte("hello world", 'o'))
fmt.Println(strings.IndexAny("hello world", "oks"))
	
han :=func(c rune) bool {
	return unicode.Is(unicode.Han, c)
}

fmt.Println(strings.IndexFunc("hello world", han))
fmt.Println(strings.IndexFunc("hello 世界", han))

输出

3
4
4
-1
6

(2)最后一次出现的位置

函数签名

func LastIndex(s, sep string) int
func LastIndexByte(s string, c byte) int
func LastIndexAny(s, chars string) int
func LastIndexFunc(s string, f func(rune) bool) int

说明

LastIndex - 在 s 中查找 sep 的第一次出现,返回最后一次出现的索引
LastIndexByte - 在 s 中查找字节 c 的第一次出现,返回最后一次出现的索引
LastIndexAny - chars 中任何一个 Unicode 代码点在 s 中最后一次出现的位置
LastIndexFunc - 查找字符 c 在 s 中最后一次出现的位置,其中 c 满足 f(c) 返回 true

示例

fmt.Println(strings.LastIndex("hello world", "lo"))
fmt.Println(strings.LastIndexByte("hello world", 'o'))
fmt.Println(strings.LastIndexAny("hello world", "oks"))

han := func(c rune) bool {
	return unicode.Is(unicode.Han, c)
}

fmt.Println(strings.LastIndexFunc("hello world", han))
// 最后一个汉字"界"出现的索引位置是9,因为在go中,一个汉字占三个字节
fmt.Println(strings.LastIndexFunc("hello 世界", han))

输出

3
7
7
-1
9
1赞

12.4 字符串替换

进行字符串替换时,考虑到性能问题,能不用正则尽量别用,应该用这里的函数。

函数签名

func Replace(s, old, new string, n int) string
func ReplaceAll(s, old, new string) string

说明

Replace - 用new替换字符串s中的old,一共替换n个。如果 n<0,则不限制替换次数,
          即全部替换

ReplaceAll - 该函数内部直接调用了函数 Replace(s, old, new, -1)

示例

fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
fmt.Println(strings.ReplaceAll("oink oink oink", "oink", "moo"))

输出

oinky oinky oink
moo moo moo
moo moo moo
1赞

12.5 统计子串出现的次数

函数签名

func Count(s, sep string) int

说明

查找子串出现次数。需要注意的是,当sep为空时,Count的返回值是:
utf8.RuneCountInString(s)+1

示例

fmt.Println(strings.Count("cheese", "e"))
fmt.Println(strings.Count("我爱你中国", ""))
// 注意:Count是计算子串在字符串中出现的无重叠的次数
fmt.Println(strings.Count("fivevev", "vev"))

输出

3
6
1
1赞

12.6 字符串重复

函数签名

func Repeat(s string, count int) string

说明

将s重复count次,如果count为负数或返回值长度len(s)超出string上限会导致panic。

示例

fmt.Println(strings.Repeat("ba", 3))

输出

bababa

12.7 大小写转换

函数签名

func ToLower(s string) string
func ToUpper(s string) string

说明

ToLower - 转换为小写字母
ToUpper - 转换为大写字母

示例

fmt.Println(strings.ToLower("HELLO WORLD"))
fmt.Println(strings.ToUpper("hello world“))

输出

hello world
HELLO WORLD

12.8 字符串修剪

函数签名

// 将s左侧和右侧中匹配cutset中的任一字符的字符去掉
func Trim(s string, cutset string) string
// 将s左侧的匹配cutset中的任一字符的字符去掉
func TrimLeft(s string, cutset string) string
// 将s右侧的匹配cutset中的任一字符的字符去掉
func TrimRight(s string, cutset string) string
// 如果s的前缀为prefix则返回去掉前缀后的string,否则s没有变化
func TrimPrefix(s, prefix string) string
// 如果s的后缀为suffix则返回去掉后缀后的string,否则s没有变化
func TrimSuffix(s, suffix string) string
// 将s左侧和右侧的间隔符去掉。常见间隔符包括 '\t'、'\n'、'\v'、'\f'、'\r'、' '
func TrimSpace(s string) string
// 将s左侧和右侧的匹配f的字符去掉
func TrimFunc(s string, f func(rune) bool) string
// 将s左侧的匹配f的字符去掉
func TrimLeftFunc(s string, f func(rune) bool) string
// 将s右侧的匹配f的字符去掉
func TrimRightFunc(s string, f func(rune) bool) string

示例

x := "!!!@@@你好,!@#$ Gophers###$$$"

fmt.Println(strings.Trim(x, "@#$!%^&*()_+=-"))
fmt.Println(strings.TrimLeft(x, "@#$!%^&*()_+=-"))
fmt.Println(strings.TrimRight(x, "@#$!%^&*()_+=-"))
fmt.Println(strings.TrimSpace(" \t\n Hello, Gophers \n\t\r\n"))
fmt.Println(strings.TrimPrefix(x, "!"))
fmt.Println(strings.TrimSuffix(x, "$"))
f := func(r rune) bool {
    return !unicode.Is(unicode.Han, r) // 非汉字返回 true
}

fmt.Println(strings.TrimFunc(x, f))
fmt.Println(strings.TrimLeftFunc(x, f))
fmt.Println(strings.TrimRightFunc(x, f))

输出

你好,!@#$ Gophers
你好,!@#$ Gophers###$$$
!!!@@@你好,!@#$ Gophers
Hello, Gophers
!!@@@你好,!@#$ Gophers###$$$
!!!@@@你好,!@#$ Gophers###$$
你好
你好,!@#$ Gophers###$$$
!!!@@@你好

12.9 字符串分割

(1)Fields 和 FieldsFunc

函数签名

func Fields(s string) []string
func FieldsFunc(s string, f func(rune) bool) []string

说明

Fields     - 用一个或多个连续的空格分割字符串s,返回[]string。其中,空格的定义
             是unicode.IsSpace(判断一个字符是否为空格)。
             常见间隔符包括:'\t','\n','\v','\f','\r',' ',U+0085 (NEL),
             U+00A0 (NBSP) 

FieldsFunc - 用这样的代码点(unicode code points)进行分隔:满足f(c)返回true。
             如果字符串s中所有的代码点都满足f(c)或者s是空,则FieldsFunc返回空
             slice。

示例

fmt.Printf("Fields are: %q", strings.Fields("   foo  bar baz"))
fmt.Println(strings.FieldsFunc("  foo bar  baz   ", unicode.IsSpace))

输出

Fields are: ["foo" "bar" "baz"]
[foo bar baz]

(2)Split 和 SplitAfter、SplitN 和 SplitAfterN

函数签名

func Split(s, sep string) []string
func SplitAfter(s, sep string) []string
func SplitN(s, sep string, n int) []string
func SplitAfterN(s, sep string, n int) []string

说明

Split       - 通过sep分割,并将s中的sep去掉,返回[]string

SplitAfter  - 通过sep分割,但保留s中的sep,返回[]string

SplitN      - 通过sep分割,并将s中的sep去掉,通过最后一个参数n控制返回的结果中
              slice的元素个数。

SplitAfterN - 通过sep分割,但保留s中的sep,通过最后一个参数n控制返回的结果中
              slice的元素个数。

当n<0时,返回所有的子字符串;
当n=0时,返回的结果是nil;
当n>0时,返回的slice中最多只与n个元素,其中,最后一个元素不会分割。

示例

fmt.Printf("%q\n", strings.Split("foo,bar,baz", ","))
fmt.Printf("%q\n", strings.SplitAfter("foo,bar,baz", ","))
fmt.Printf("%q\n", strings.SplitN("foo,bar,baz", ",", -1))
fmt.Printf("%q\n", strings.SplitN("foo,bar,baz", ",", 0))
fmt.Printf("%q\n", strings.SplitN("foo,bar,baz", ",", 2))
fmt.Printf("%q\n", strings.SplitAfterN("foo,bar,baz", ",", 2))

输出

["foo" "bar" "baz"]
["foo," "bar," "baz"]
["foo" "bar" "baz"]
[]
["foo" "bar,baz"]
["foo," "bar,baz"]

12.10 字符串拼接

函数签名

func Join(a []string, sep string) string

说明

通过sep将字符串数组中的元素连接起来。

示例

fmt.Println(strings.Join([]string{"name=xxx", "age=xxx"}, "&"))

输出

name=xxx&age=xxx

12.11 标题处理

函数签名

func Title(s string) string
func ToTitle(s string) string

说明

Title - 将s每个单词的首字母大写,不处理该单词的后续字符。
ToTitle - 将s的每个字母大写。

示例

fmt.Println(strings.Title("hElLo wOrLd"))
fmt.Println(strings.ToTitle("hElLo wOrLd"))

输出

HElLo WOrLd
HELLO WORLD