初始化
- str := "Hello World! \n Hello Gopher! \n" 使用双引号初始化,会自动转义符。
- str := `Hello World! \n Hello Gopher! \n` 使用反引号初始化,相关的转义字符不会被替换。哈哈哈,可惜不能在里面跟JavaScript一样使用${var}插入变量。
一些笔记说明
- Go 语言中的string类型是一种值类型,存储的字符串是不可变的,如果要修改string内容需要将string转换为[]byte或[]rune,并且修改后的string内容是重新分配的。string 内部使用rune实现,其中rune的类型是
type rune = int32
,字节byte的类型是type byte = uint8
。 - string类型的零值是为长度为零的字符串,即空字符串 ``
- 可使用的运算符有 ==、!=、<、<=、>=、>
- 通过函数 len() 来获取字符串所占的字节长度,例如:len(str),注意是字节byte,不是rune。
- 可通过下标的方式获取字节内容。如str[0], str[1], ... , str[len(str) - 1]
- 如果需要获取字符的长度,需要使用内置的包
unicode/utf8
。如:
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
s := "我是rune"
fmt.Println(len(s)) // 10 (一个utf-8占用三个字节 2*3+4 = 10)
fmt.Println(utf8.RuneCountInString(s)) // 6
}
- for range循环处理字符时,不是按照字节的方式来处理的。value其实际上是一个rune类型值。range循环在处理字符串的时候,会自动隐式解码UTF8字符串。
package main
import (
"fmt"
)
func main() {
s := "我爱yijia"
for index, value := range s {
fmt.Printf("%d, %c, %d\n", index, value, value)
}
}
// 输出如下。注意看索引,汉字不是连续的。相差了3个字节。
// 0, 我, 25105
// 3, 爱, 29233
// 6, y, 121
// 7, i, 105
// 8, j, 106
// 9, i, 105
// 10, a, 97
字符串处理总结
标准库中提供了四个包用来对字符串处理,分别是:bytes、strings、strconv和unicode包。
- strings:提供了许多如字符串的查询、替换、比较、截断、拆分和合并等功能。
- bytes:包也提供了很多类似功能的函数,但是针对和字符串有着相同结构的[]byte类型。因为字符串是只读的,因此逐步构建字符串会导致很多分配和复制。在这种情况下,使用bytes.Buffer类型将会更有效。
- strconv:提供了布尔型、整型数、浮点数和对应字符串的相互转换,还提供了双引号转义相关的转换。
- unicode:提供了IsDigit、IsLetter、IsUpper和IsLower等类似功能,用于给字符分类。
字符串的拼接
- 直接使用运算符`+`或者 `+=`。
由于编译器行尾自动补全分号的缘故,如果需要换行,加号 + 必须放在第一行。如下
str := "Beginning of the string " +
"second part of the string"
s := "hel" + "lo, "
s += "world!"
fmt.Println(s) // 输出 hello, world!
- fmt.Sprintf()
fmt.Sprintf("%d:%s", 2018, "年")
- strings.Join()
strings.Join([]string{"hello", "world"}, ", ")
- bytes.Buffer
推荐使用,性能比较好
var buffer bytes.Buffer
buffer.WriteString("hello")
buffer.WriteString(", ")
buffer.WriteString("world")
fmt.Print(buffer.String())
- strings.Builder
strings.Builder 内部通过 slice 来保存和管理内容,非线程安全。
var b1 strings.Builder
b1.WriteString("ABC")
b1.WriteString("DEF")
fmt.Print(b1.String())