Go 的字符串内部实现使用 UTF-8 编码,字符串是 UTF-8 字符的一个序列,当字符为 ASCII 码时则占用 1 个字节,其他字符根据需要占用 2-4 个字节。因此 Go 中的字符串里面的字符可能根据需要占用 1 至 4 个字节。Go 这样做的好处是① 减少内存和硬盘空间占用;② 不需要对使用 UTF-8 字符集的文本进行编码和解码。
Go 的字符串的值为双引号""
中的内容,可以直接在 Go 语言的源码中直接添加非 ASCII 码字符。
Go 的字符串是一种值类型且值不可变,即创建某个文本后无法对其进行修改。深入一点讲就是:字符串是字节的定长数组。
Go 的字符串是根据长度限定,字符串类型的零值为长度为零的字符串,即空字符串""
一般的比较运算符(==
、!=
、<
、<=
、>=
、>
)通过在内存中按字节比较来实现字符串的对比
Go 支持以下 2 种形式的字面值:
该类字符串使用双引号括起来,其中相关的转义字符将被替换,转义字符有:
\n
:换行符(直接跳到下一行的同列位置)\r
:回车符(返回行首)\t
:tab 键(制表符)\'
:单引号\"
:双引号\\
:反斜杠自身\u
或 \U
:Unicode字符该类字符串使用反引号括起来,支持换行,可以用来定义多行字符串,例:
str := `第一行
第二行
第三行\n
`
fmt.Println(str)
该类字符串反引号间换行将被视为字符串中的换行,但是所有的转义字符均无效,按照原样输出
Go 中使用 strings
包和 strconv
包完成对字符串的主要操作
HasPrefix
判断字符串 s
是否以某段字符串序列 prefix
开头(前缀):
strings.HasPrefix(s, prefix string) bool
HasSuffix
判断字符串 s
是否以某段字符串序列 suffix
结尾(后缀):
strings.HasSuffix(s, suffix string) bool
示例 1 :
package main
import (
"fmt"
"strings"
)
func main() {
str := "llwwwhh" // 声明字符串 str
// 判断字符串 str 是否存在前缀 ll, 返回一个 bool 类型的值
pre := strings.HasPrefix(str, "ll")
// 判断字符串 str 是否存在后缀 ww, 返回一个 bool 类型的值
suf := strings.HasSuffix(str, "hh")
if pre {
fmt.Println("pre is exist.")
} else {
fmt.Println("pre is not exist.")
}
if suf {
fmt.Println("suf is exist.")
} else {
fmt.Println("suf is not exist.")
}
}
输出:
pre is exist.
suf is exist.
Contains
判断字符串 str
是否包含某段字符串序列 substr
:
strings.Contains(str, substr string) bool
示例 2:
package main
import (
"fmt"
"strings"
)
func main() {
str := "llwwwhh" // 声明字符串 str
// 判断字符串 str 是否包含 ww, 返回一个 bool 类型的值
flag := strings.Contains(str, "ww")
if flag {
fmt.Println("str contains ww.")
} else {
fmt.Println("str does not contains ww.")
}
}
输出:
str contains ww.
判断子字符串或字符在父字符串中出现的位置(索引):
Index
返回字符串 s
在字符串 str
中的索引(s
的第一个字符的索引),-1 表示字符串 s
不包含字符串 str
:
strings.Index(str, s string) int
LastIndex
返回字符串 s
在字符串 str
中最后出现位置的索引(s
的第一个字符的索引),-1 表示字符串 str
不包含字符串 s
:
strings.LastIndex(str, s string) int
如果需要查询非 ASCII 编码的字符在字符串中的位置,建议使用以下函数来对字符进行定位:
strings.IndexRune(str string, r rune) int
注意:
该方法在最新版本的 Go 中定义为 func IndexRune(s string, r rune) int
实际使用中的第二个参数 rune 可以是 rune 或 int,如 strings.IndexRune(“chicken”, 99) 或 strings.IndexRune(“chicken”, rune(‘k’))
示例 3:
package main
import (
"fmt"
"strings"
)
func main() {
str := "llwwwhh" // 声明字符串 str
s := "ww" // 声明字符串 s
// 返回字符串 s 在字符串 str 中的索引
index := strings.Index(str, s)
// 返回字符串 s 在字符串 str 中最后出现位置的索引
lastIndex := strings.LastIndex(str, s)
fmt.Println(index)
fmt.Println(lastIndex)
}
输出:
2
3
Replace
用于将字符串 str
中的前 n
个字符串 old
替换为新字符串 new
,并返回一个新的字符串,如果 n = -1
则替换所有字符串 old
为新字符串 new
:
strings.Replace(str, old, new, n) string
示例:
package main
import (
"fmt"
"strings"
)
func main() {
str := "llwwwhh" // 声明字符串 str
// 替换字符串中前2个"ll"字符串为新字符串"LL"
newStr := strings.Replace(str, "ll", "LL", 2)
fmt.Println(newStr)
}
输出:
LLwwwhh
Count
用于计算字符串 s
在字符串 str
中出现的非重叠次数:
strings.Count(str, s string) int
示例:
package main
import (
"fmt"
"strings"
)
func main() {
// 声明一个字符串 str
str := "You are the apple of my eye."
// 声明一个字符串 s
s := "a"
// 计算字符串 s 在字符串 str 中出现的非重叠次数
aCount := strings.Count(str, s)
fmt.Println(aCount)
}
输出:
2
Repeat
用于重复 count
次字符串 str
并返回一个新的字符串:
strings.Repeat(str, count int) string
示例:
package main
import (
"fmt"
"strings"
)
func main() {
// 声明一个字符串 str
str := "Come here!"
// 声明一个int整型 count
count := 3
// 使字符串 str 重复出现 count 次,返回一个新字符串
newStr := strings.Repeat(str, count)
fmt.Println(newStr)
}
输出:
Come here!Come here!Come here!
ToLower
将字符串中的 Unicode 字符全部转换成相应的小写字符:
strings.ToLower(str) string
ToUpper
将字符串中的 Unicode 字符全部转换为相应的大写字符:
strings.ToUpper(str) string
示例:
package main
import (
"fmt"
"strings"
)
func main() {
// 声明一个字符串 str1
str1 := "I LIKE YOU."
// 声明一个字符串 str2
str2 := "i love you."
// 将字符串 str1 的大写字母全部转为小写字母
lowerStr := strings.ToLower(str1)
// 将字符串 str2 的小写字母全部转为大写字母
uppperStr := strings.ToUpper(str2)
fmt.Println(lowerStr)
fmt.Println(uppperStr)
}
输出:
i like you.
I LOVE YOU.
TrimSpace
可以剔除字符串 str
开头和结尾的空白符号
strings.TrimSpace(str)
Trim
可以剔除字符串 str
开头和结尾的指定字符串 s
,第二个参数可以是任何字符
strings.Trim(str, s string)
TrimLeft
可以只剔除开头的字符串 s
strings.TrimLeft(str, s string)
TrimRight
可以只剔除结尾的字符串 s
strings.TrimRight(str, s string)
示例:
package main
import (
"fmt"
"strings"
)
func main() {
// 1、剔除字符串开头和结尾的空白符号
// 声明一个字符串 str
str1 := " a=1,b=2,c=3,d=4 "
// 剔除字符串 str 开头和结尾的空白符号
newStr1 := strings.TrimSpace(str1)
fmt.Println("str1:" + str1 + "结束--")
fmt.Println("newStr1:" + newStr1 + "结束--")
// 2、剔除字符串开头和结尾的指定字符
// 声明一个字符串 str2
str2 := "cutLWHcut"
// 声明一个字符串 s,也是要从字符串str2中剔除的指定字符
s := "cut"
// 剔除字符串 str2 开头和结尾的指定字符 s
newStr2 := strings.Trim(str2, s)
fmt.Println("str2:" + str2)
fmt.Println("newStr2:" + newStr2)
// 3、只剔除字符串开头的字符
str3 := "comeHOWcome"
newStr3 := strings.TrimLeft(str3, "come")
fmt.Println("str3:" + str3)
fmt.Println("newStr3:" + newStr3)
// 4、只剔除字符串结尾的字符
str4 := "comeHOWcome"
newStr4 := strings.TrimRight(str4, "come")
fmt.Println("str4:" + str4)
fmt.Println("newStr4:" + newStr4)
}
输出:
str1: a=1,b=2,c=3,d=4 结束--
newStr1:a=1,b=2,c=3,d=4结束--
str2:cutLWHcut
newStr2:LWH
str3:comeHOWcome
newStr3:HOWcome
str4:comeHOWcome
newStr4:comeHOW
Fileds
会利用 1 个或多个空白符号来作为动态长度的分隔符将字符串 str
分割成若干小块,并返回一个 slice,如果字符串只包含空白符号,则返回一个长度为 0 的 slice
strings.Fields(str)
Split
用于自定义分割符号 sep
来对指定字符串 str
进行分割,同样返回 slice
strings.Split(str, sep)
这两个函数都会返回 slice,所以习惯使用 for-range
循环对其进行处理
示例:
package main
import (
"fmt"
"strings"
)
func main() {
// 1、利用 1 个或多个空白符号来作为动态长度的分隔符将字符串 str 分割成若干小块,返回 slice
// 声明一个字符串 str1
str1 := "t l j swhi "
// 分割字符串 str1
slice1 := strings.Fields(str1)
fmt.Println("slice1:")
// for-range 遍历 slice1 输出
for _, value1 := range slice1 {
fmt.Println(value1)
}
// 2、使用自定义分割符号 sep 来对指定字符串 str 进行分割,返回 slice
// 声明一个字符串 str2
str2 := "a=1, b=2, c=3, d=4"
// 自定义分割符号 sep
sep := ","
// 以 sep 分割字符串 str2
slice2 := strings.Split(str2, sep)
fmt.Println("\nslice2:")
// for-range 遍历 slice2 输出
for _, value2 := range slice2 {
fmt.Println(value2)
}
}
输出:
slice1:
t
l
j
swhi
slice2:
a=1
b=2
c=3
d=4
Join
用于将元素类型为 string
的 slice
使用分割符号 sep
拼接组成一个字符串:
strings.Join(sl []string, sep string) string
示例:
package main
import (
"fmt"
"strings"
)
func main() {
// 声明一个字符串 str
str1 := "Go|The Way to Go|Effective Go"
// 自定义分割符号 sep1
sep1 := "|"
// 以 sep1 分割字符串 str1
sl1 := strings.Split(str1, sep1)
fmt.Println("sl1:")
// for-range 遍历 sl1 输出
for _, value := range sl1 {
fmt.Println(value)
}
fmt.Println()
// 自定义分割符号 sep2
sep2 := ";"
// 将元素类型为 string 的 slice 使用分隔符号 sep2 拼接组成字符串
str2 := strings.Join(sl1, sep2)
fmt.Println(str2)
}
输出:
sl1:
Go
The Way to Go
Effective Go
Go;The Way to Go;Effective Go
NewReader
用于生成一个 Reader
并读取字符串 str
中的内容,然后返回指向该 Reader
的指针
strings.NewReader(str)
从其他类型读取内容的函数还有:
Read()
从 []byte
中读取内容ReadByte()
和 ReadRune()
从字符串中读取下一个 byte 或者 runestrconv 包实现了基本数据类型与其字符串表示的转换,主要有以下常用函数:Atoi()、Itia()、parse系列、format系列、append系列,该包还包含了一些变量用于获取程序运行的操作系统平台下 int 类型所占的位数,如:strconv.IntSize
。
任何类型 T 转换为字符串总是成功的。
Itoa
用于将 int 类型数据转换为对应的字符串表示:
strconv.Itoa(i int) string
也就是返回数字 i 所表示的字符串类型的十进制数
【扩展】a 的典故:C 语言中没有 string 类型而是用字符数组(array)表示字符串
FormatFloat
用于将 64 位浮点型的数字转换为字符串,其中 fmt
表示格式(其值可以是 b
、e
、f
或 g
),prec
表示精度,bitSize
使用 32 表示 float32,用 64 表示 float64
将字符串转换为其他类型 T 并不总是可能的,可能会在运行时抛出错误 parsing "...": invalid argument
Atoi
用于将字符串类型的整数转换为 int 类型:
strconv.Atoi(s string) (i int, err error)
ParseFloat
用于将字符串转换为 float64 类型:
strconv.ParseFloat(s string, bitSize int) (f float64, err error)
bitSize
使用 32 表示 float32,用 64 表示 float64
这些函数都会返回 2 个值,第 1 个是转换后的结果(如果转换成功),第 2 个是可能出现的错误,因此,一般使用以下形式进行从字符串到其它类型的转换:
val, err = strconv.Atoi(s)