字符串类型string是一个不可变的字符序列,go从底层就采用UTF-8编码。
字符串在内存中是以byte数组存储的,如果是非ASCII字符的其他长度字符(如中文),每个rune就占多个byte。
//转义字符\n \r \t \u \U分别表示换行,回车,制表符,Unicode字符
var str string = "测试转义字符: \t hello \u0067\U0000006F \n"
//使用反引号来定义原生字符串,无需转义原样输出
var str1 string = `使用反引号来定义原生字符串: hello
go
你好
golang
`
fmt.Print(str, str1)
//一个ascii字符占1字节,一个中文字符占3字节。
fmt.Printf("字符串'你好,go'的长度:%d", len("你好,go"))
// 输出
测试转义字符: hello go
使用反引号来定义原生字符串:hello
go
你好
golang
字符串'你好,go'的长度:9
== != < <= > >=
操作,这些操作都是按照底层byte数组顺序比较的。s1, s2 := "你好,go", "你好,\u0067\U0000006F"
fmt.Println("s1 == s2? ", s1 == s2)
//输出:true
fmt.Printf("内存长度:%d\n", len("你好,go")) //输出 9
fmt.Printf("rune长度:%d\n", utf8.RuneCountInString("你好,go")) //输出 5
fmt.Printf("字符串'你好,go'的第8个byte为:%c\n", "你好,go"[7]) //输出: g
//取rune,先将string转为rune数组,在按索引取
fmt.Printf("字符串'你好,go'的第2个rune为:%v\n", string([]rune("你好,go")[1])) //输出:好
//方法一:使用+拼接,效率相对较低,适用于少量字符串拼接
fmt.Print("hello " + " go" + "\n")
//方法二:使用bytes.Buffer拼接,效率高,节省内存
var stringBuilder bytes.Buffer
stringBuilder.WriteString("你好")
stringBuilder.WriteString("go")
fmt.Println(stringBuilder.String())
//方法三:使用fmt.Sprintf
fmt.Println(fmt.Sprintf("%s %s", "你好,", "go"))
s3 := "hello,go"
s4 := "你好,go"
//遍历byte序列,对于ASCII序列,这样遍历与预期一致
fmt.Print("遍历byte序列:")
for i := 0; i < len(s3); i++ {
fmt.Printf("%c\t", s3[i])
}
fmt.Printf("\n%s", "遍历rune序列:")
//遍历rune序列,对于非ASCII遍历,需要使用这种方式遍历
//这里index返回的是rune字符第一个byte的index
for index, c := range s4 {
fmt.Printf("s4[%d]=%c\t", index, c)
}
fmt.Println()
//子串查找
fmt.Printf("第一个lo的索引:%d,", strings.Index("hello hello go", "lo")) //输出 3
fmt.Printf("截取第一个lo之前的子串:%s, ", s5[:strings.Index(s5, "lo")]) //输出 hel
fmt.Printf("最后一个lo的索引:%d", strings.LastIndex("hello hello go", "lo")) //输出9
由于string类型变量是一个不可变的字符序列,如果要修改字符串,需要将其强制转换为[ ]byte
,修改之后再赋值会原来的变量。
//修改字符串,将s5的第一个hello改成xxxxx
bytes := []byte(s5)
for i := 0; i < 5; i++ {
bytes[i] = 'x'
}
s5 = string(bytes)
fmt.Println(s5)
//将"hello go,我正在学习"中的"go"替换为"world"
s6 := "hello go,我正在学习"
src := "go"
target := "world"
var stringBuilder1 bytes.Buffer
index := strings.Index(s6, src)
stringBuilder1.WriteString(s6[:index])
stringBuilder1.WriteString(target)
stringBuilder1.WriteString(s6[index+len(src):])
fmt.Println(stringBuilder1.String())
主要介绍了字符串相关操作。
package main
import (
"bytes"
"fmt"
"strings"
"unicode/utf8"
)
func main() {
//string使用,转义字符\n \r \t \u \U分别表示换行,回车,制表符,Unicode字符
var str string = "测试转义字符: \t 你好,\u0067\U0000006F\n"
//使用反引号来定义原生字符串,无需转义原样输出
var str1 string = `使用反引号来定义原生字符串: 你好,
go
`
fmt.Print(str, str1)
//字符串比较
s1, s2 := "你好,go", "你好,\u0067\U0000006F"
fmt.Println("s1 == s2? ", s1 == s2)
//一个ascii字符占1字节,一个中文字符占3字节。
fmt.Printf("字符串'你好,go'的内存长度:%d\n", len("你好,go"))
fmt.Printf("字符串'你好,go'的rune长度:%dv\n", utf8.RuneCountInString("你好,go"))
//字符访问
fmt.Printf("字符串'你好,go'的第8个byte为:%c\n", "你好,go"[7])
fmt.Printf("字符串'你好,go'的第2个rune为:%v\n", string([]rune("你好,go")[1]))
//字符串拼接
//方法一:使用+拼接,效率相对较低,适用于少量字符串拼接
fmt.Print("hello " + " go" + "\n")
//方法二:使用bytes.Buffer拼接,效率高,节省内存
var stringBuilder bytes.Buffer
stringBuilder.WriteString("你好")
stringBuilder.WriteString("go")
fmt.Println(stringBuilder.String())
//方法三:使用fmt.Sprintf
fmt.Println(fmt.Sprintf("%s %s", "你好,", "go"))
//遍历
s3 := "hello,go"
s4 := "你好,go"
//遍历byte序列,对于ASCII序列,这样遍历与预期一致
fmt.Print("遍历byte序列:")
for i := 0; i < len(s3); i++ {
fmt.Printf("%c\t", s3[i])
}
fmt.Printf("\n%s", "遍历rune序列:")
//遍历rune序列,对于非ASCII遍历,需要使用这种方式遍历
//这里index返回的是rune字符第一个byte的index
for index, c := range s4 {
fmt.Printf("s4[%d]=%c\t", index, c)
}
fmt.Println()
//子串查找
s5 := "hello hello go"
fmt.Printf("第一个lo的索引:%d, ", strings.Index(s5, "lo"))
fmt.Printf("截取第一个lo之前的子串:%s, ", s5[:strings.Index(s5, "lo")])
fmt.Printf("最后一个lo的索引:%d", strings.LastIndex(s5, "lo"))
}
输出
测试转义字符: 你好,go
使用反引号来定义原生字符串: 你好,
go
s1 == s2? true
字符串'你好,go'的内存长度:9
字符串'你好,go'的rune长度:5v
字符串'你好,go'的第8个byte为:g
字符串'你好,go'的第2个rune为:好
hello go
你好go
你好, go
遍历byte序列:h e l l o , g o
遍历rune序列:s4[0]=你 s4[3]=好 s4[6]=, s4[7]=g s4[8]=o
第一个lo的索引:3, 截取第一个lo之前的子串:hel, 最后一个lo的索引:9%