Go语言中的字符串以原生数据类型出现,使用字符串就像使用其他原生数据类型(int、bool、float32、float64 等)一样。一个字符串是一个不可改变的字节序列。字符串可以包含任意的数据,包括byte值0,但是通常是用来包含人类可读的文本。
Go语言中的字符串的内部实现使用UTF-8编码。 字符串的值为双引号(")中的内容,可以在Go语言的源码中直接添加非ASCII码字符,例如:
s1 := "hello, world"
s2 := "凯冰科技"
fmt.Println(len(s1)) // "12"
fmt.Println(s1[0], s1[7]) // "104 119" ('h' and 'w')
内置的len函数可以返回一个字符串中的字节数目,索引操作s[i]返回第i个字节的字节值(0 ≤ i< len(s))。访问超出字符串索引范围的字节将会导致panic异常(panic: index out of range)。
一、字符串转义符
Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等,如下表所示。
转义 | 含义 |
---|---|
\r | 回车符(返回行首) |
\n | 换行符(直接跳到下一行的同列位置) |
\t | 制表符 |
\' | 单引号 |
\" | 双引号 |
\ | 反斜杠 |
打印一个windows平台下的文件路径:
fmt.Println("str := \"c:\\pprof\\main.exe\"")
二、多行文本
Go语言中要定义一个多行字符串时,就必须使用反引号字符。多行文本时,里面的转义字符将无效,文本将会原样输出。
s1 := `第一行
第二行
第三行
`
fmt.Println(s1)
三、byte和rune类型
组成每个字符串的元素叫做“字符”,可以通过遍历或者单个获取字符串元素获得字符。 Go 语言的字符有以下两种:
- uint8类型,或者叫 byte 型,代表了ASCII码的一个字符
- rune类型,代表一个 UTF-8字符,实际是一个int32
rune类型在处理中文、日文或者其他复合字符时用到。
字符串底层是一个byte数组,所以可以和[]byte类型相互转换。
四、字符串的常见操作
1.截取
子字符串操作s[i:j]基于原始的s字符串的第i个字节开始到第j个字节(并不包含j本身)生成一个新字符串。i和j可忽略,i忽略时0作为起始位置,j忽略时,len(s)作为结束位置。
fmt.Println(s[0:5]) // "hello"
fmt.Println(s[:5]) // "hello"
fmt.Println(s[7:]) // "world"
fmt.Println(s[:]) // "hello, world"
2.连接
+操作符将两个字符串连接构造一个新字符串。还可使用fmt.Sprintf拼接字符串。
fmt.Println("goodbye" + s[5:]) // "goodbye, world"
title := fmt.Sprintf("goodbye%s", s[5:])
字符串连接操作+在数据量大时代价高昂,一种简单且高效的解决方案是使用strings包的Join函数:
fmt.Println(strings.Join(s[1:], "zkbhj"))
3.比较
==和<进行比较,通过逐个字节比较完成的,因此比较的结果是字符串自然编码的顺序。
4.修改
字符串的值是不可变的:一个字符串包含的字节序列永远不会被改变。如下面的操作并不会改变t的值。当然尝试修改字符串内部数据的操作也是被禁止的。
s := "left foot"
t := s
s += ", right foot"
fmt.Println(s) // "left foot, right foot"
fmt.Println(t) // "left foot"
s[0] = 'L' // compile error: cannot assign to s[0]
不变性意味着如果两个字符串共享相同的底层数据的话也是安全的,这使得复制任何长度的字符串代价是低廉的。同样,一个字符串s和对应的子字符串切片s[7:]的操作也可以安全地共享相同的内存,因此字符串切片操作代价也是低廉的。在这两种情况下都没有必要分配新的内存。
变相的修改是,先把字符串强制转换为[]rune或[]byte,修改之后,再强制转换为string。
func changeString() {
s1 := "zkbhj.com"
// 强制类型转换
byteS1 := []byte(s1)
byteS1[0] = 'Z'
fmt.Println(string(byteS1))
s2 := "凯冰科技"
runeS2 := []rune(s2)
runeS2[0] = '好'
fmt.Println(string(runeS2))
}
5.转换
字符串和数值之间的转换比较常见,这个可以通过 strconv包 提供的转换功能来实现。
x := 123
//用fmt.Sprintf返回一个格式化的字符串
y := fmt.Sprintf("%d", x)
//strconv.Itoa(“整数到ASCII”)
fmt.Println(y, strconv.Itoa(x)) // "123 123"
//用不同的进制来格式化数字
fmt.Println(strconv.FormatInt(int64(x), 2)) // "1111011"
//fmt.Sprintf函数附加额外信息
s := fmt.Sprintf("x=%b", x) // "x=1111011"
//Atoi字符串解析为整数
x, err := strconv.Atoi("123") // x is an int
//ParseInt字符串解析为整数
y, err := strconv.ParseInt("123", 10, 64) // base 10, up to 64 bits
6.其他操作
len(str) //求长度
data := strings.Split(s, ',') //分割
data := strings.Contains(s, ',') //判断是否包含
data := strings.HasPrefix(s, 'h') //前缀判断
data := strings.HasSuffix(s, '!') //后缀判断
data := strings.Index(s, '!') //子串出现的位置
data := strings.LastIndex(s, '!') //子串出现的位置
strings.Join(a[]string, sep string) // join操作(比+连接符更高效)
五、字符串面值
因为Go语言源文件总是用UTF8编码,并且Go语言的文本字符串也以UTF8编码的方式处理,因此我们可以将Unicode码点也写到字符串面值中。
一个原生的字符串面值形式是`...`,使用反引号代替双引号。原生字符串面值用于编写正则表达式会很方便,因为正则表达式往往会包含很多反斜杠。原生字符串面值同时被广泛应用于HTML模板、JSON面值、命令行提示信息以及那些需要扩展到多行的场景。
Go语言字符串部分的内容就总结到这里,你GET到了吗?