Go字符串详解[TOC]总结:字符串是不可变值类型,内部⽤指针指向 UTF-8 字节数组。默认值是空字符串 “"。⽤索引号访问某字节,如 s[i]。取出的是字节,不是字符不能⽤序号获取字节元素指针, &s[i] ⾮法。不可变类型,⽆法修改字节数组。使用[]rune进行修改是重新分配内存,并复制字节数组字符串可以用==和<进行比较;go语言的字符串是utf-8的定长字符序列,会自动转为Unicode,然后可以通过[]rune按索引取出字符。1、字符串的定义在Go语言中,字符串字面量使用双引号 "” 或者反引号 ’ 来创建。双引号用来创建可解析的字符串,支持转义,但不能用来引用多行;反引号用来创建原生的字符串字面量,可能由多行组成,但不支持转义,并且可以包含除了反引号外其他所有字符。双引号创建可解析的字符串应用最广泛,反引号用来创建原生的字符串则多用于书写多行消息,HTML以及正则表达式。s:=“今天很开心"s:=今天开心吗 不开心啊 真的?2、字符串操作(1)字符串支持 + 连接操作和+=追加操作连接跨⾏字符串时, “+” 必须在上⼀⾏末尾,否则导致编译错误。s := “Hello, " + “World!“s2 := “Hello, " + “World!” // Error: invalid operation: + untyped strings+=“abc” 其他函数连接这里暂不说明(2)⽀持⽤两个索引号返回⼦串。⼦串依然指向原字节数组,仅修改了指针和⻓度属性。s := “Hello, World!“s1 := s[:5] // Hellos2 := s[7:] // World!s3 := s[1:5] // ello注意:如果字符串中有汉字,汉字占得就是3个字节,所以就不一定能取出(3)字符串底层分析struct String{//字符串是个不可变值类型, 存储了字节和长度 byte* str; intgo len;};字符串是 UTF-8 字符的一个序列(当字符为 ASCII 码时则占用 1 个字节,其它字符根据需要占用 2-4 个字节) go语言中字符串的字节使用UTF-8编码表示Unicode文本。因此Go语言字符串是变宽字符序列,每一个字符都用一个或者多个字符表示,这跟其他的(C++,Java,Python 3)的字符串类型有着本质上的不同,后者为定宽字符序列。每一个Unicode字符都有一个唯一的叫做“码点”的标识数字。在Go语言中,一个单一的码点在内存中以 rune 的形式表示,rune表示int32类型的别名。可以将Go语言的字符串转化为Unicode码点切片(类型为 [ ]rune),切片是支持直接索引的。package mainimport( “fmt”)func main() { s:=“abc好好学习” fmt.Println(s) for _,b:=range []byte(s){ fmt.Printf("%x “,b) //打印16进制 } fmt.Println("\n字节长度:",len(s)) for i,ch:=range s{ //ch 是rune int32别名4个字节 fmt.Printf(”(%d %x)",i,ch) } fmt.Println() for i,ch:=range []rune(s){ fmt.Printf(”(%d %c)",i,ch) }}//输出结果abc好好学习61 62 63 e5 a5 bd e5 a5 bd e5 ad a6 e4 b9 a0 字节长度: 15(0 61)(1 62)(2 63)(3 597d)(6 597d)(9 5b66)(12 4e60)(0 a)(1 b)(2 c)(3 好)(4 好)(5 学)(6 习)上面代码显示,我们把字符串转为[]bype数组,打印出utf-8的字节,可以看到“学”这个汉字占了e5 ad a6三个16进制字节。看到一个汉字占3个字节,一个英文字母占1个字节,utf-8是可变宽度。遍历s,取出的是Unicode码,可以看到“学”这个汉字的Unicode是 5b66,它是从第9个开始的,(9 5b66)。将字符串转为[]rune 也就是int32的别名,占4个字节。打印出了abc好好学习。说明:go语言的字符串是utf-8的定长字符序列,会自动转为Unicode,然后可以通过[]rune按索引取出字符。3、String包的使用查找操作func Contains(s, substr string) boolfunc Index(s, sep string) intfunc Count(s, sep string) int重复操作func Replace(s, old, new string, n int) string删除操作func Trim(s string, cutset string) string大小写转换func Title(s string) stringfunc ToLower(s string) stringfunc ToUpper(s string) string字符串前缀后缀func HasPrefix(s, prefix string) boolfunc HasSuffix(s, suffix string) bool字符串分割func Split(s, sep string) []stringfunc Fields(s string) []string查找操作判断给定字符串s中是否包含子串substr, 找到返回true, 找不到返回falsefunc Contains(s, substr string) bool实例如下:package mainimport ( “fmt” “strings”)func main() { fmt.Println(“包含子串返回:”, strings.Contains(“oldboy”, “boy”)) fmt.Println(“不包含子串返回:”, strings.Contains(“oldboy”, “girl”)) fmt.Println(“子字符串是空字符串返回:”, strings.Contains(“hello”, “”)) fmt.Println(“原字符串、子字符串都是空字符串返回:”, strings.Contains(””, “”)) fmt.Println(“中文字符串包含子串返回:”, strings.Contains(“我很帅”, “帅”))}运行结果:包含子串返回: true不包含子串返回: false子字符串是空字符串返回: true原字符串、子字符串都是空字符串返回: true中文字符串包含子串返回: true在字符串s中查找sep所在的位置, 返回位置值, 找不到返回-1func Index(s, sep string) int实例如下:package mainimport ( “fmt” “strings”)func main() { fmt.Println(“存在返回第一个匹配字符的位置:”, strings.Index(“heloboy”, “boy”)) fmt.Println(“不存在返回:”, strings.Index(“helo”, “day”)) fmt.Println(“中文字符串存在返回:”, strings.Index(“我很帅”, “很帅”))}运行结果:存在返回第一个匹配字符的位置: 4不存在返回: -1中文字符串存在返回: 3 //这里是按照字节的顺序返回 一个汉字是3个字节,所以这个是从索引为3的开始统计给定子串sep的出现次数, sep为空时, 返回字符串的长度 + 1func Count(s, sep string) int实例如下:package mainimport ( “fmt” “strings”)func main() { fmt.Println(“子字符串出现次数:”, strings.Count(“hello world”, “o”)) fmt.Println(“子字符串为空时, 返回:”, strings.Count(“hello”, “”))}运行结果:子字符串出现次数: 2子字符串为空时, 返回: 6重复操作重复s字符串count次, 最后返回新生成的重复的字符串func Repeat(s string, count int) string实例如下:package mainimport ( “fmt” “strings”)func main() { fmt.Println(strings.Repeat(“嘀嗒”, 4), “时针它不停在转动”)}运行结果:嘀嗒嘀嗒嘀嗒嘀嗒 时针它不停在转动替换操作在s字符串中, 把old字符串替换为new字符串,n表示替换的次数,如果n<0会替换所有old子串。func Replace(s, old, new string, n int) string实例如下:package mainimport ( “fmt” “strings”)func main() { fmt.Println(strings.Replace(“hel hel hel”, “l”, “llo”, 2)) fmt.Println(strings.Replace(“hel hel hel”, “l”, “llo”, -1))}运行结果:hello hello helhello hello hello删除操作删除在s字符串的头部和尾部中由cutset指定的字符, 并返回删除后的字符串func Trim(s string, cutset string) string实例如下:package mainimport ( “fmt” “strings”)func main() { fmt.Println(strings.Trim(” hello “, " “))}运行结果:hello大小写转换给定字符串转换为英文标题的首字母大写的格式(不能正确处理unicode标点)func Title(s string) string返回将所有字母都转为对应的小写版本的拷贝func ToLower(s string) string返回将所有字母都转为对应的大写版本的拷贝func ToUpper(s string) string实例如下:package mainimport ( “fmt” “strings”)func main() { fmt.Println(strings.Title(“It is never too late to learn.”)) fmt.Println(strings.ToLower(“It Is Never Too Late To Learn.”)) fmt.Println(strings.ToUpper(“It is never too late to learn.”))}运行结果:It Is Never Too Late To Learn.it is never too late to learn.IT IS NEVER TOO LATE TO LEARN.字符串前缀后缀判断字符串是否包含前缀prefix,大小写敏感func HasPrefix(s, prefix string) bool判断s是否有后缀字符串suffix,大小写敏感func HasSuffix(s, suffix string) bool实例如下:package mainimport ( “fmt” “strings”)func main() { fmt.Println(“前缀是以hello开头的:”, strings.HasPrefix(“helloworld”, “hello”)) fmt.Println(“后缀是以world开头的:”, strings.HasSuffix(“helloworld”, “world”))}运行结果:前缀是以hello开头的: true后缀是以world开头的: true字符串分割用去掉s中出现的sep的方式进行分割,会分割到结尾,并返回生成的所有片段组成的切片(每一个sep都会进行一次切割,即使两个sep相邻,也会进行两次切割)。如果sep为空字符,Split会将s切分成每一个unicode码值一个字符串。func Split(s, sep string) []string返回将字符串按照空白(unicode.IsSpace确定,可以是一到多个连续的空白字符)分割的多个字符串。如果字符串全部是空白或者是空字符串的话,会返回空切片。func Fields(s string) []string实例如下://如果要分割的字符串位于字符串两端,会多出一个空字符串package mainimport ( “fmt” “strings”)func main() { fmt.Println(“Split 函数的用法”) fmt.Printf("%q\n”, strings.Split(“Linux,Python,Golang,Java”, “,”)) fmt.Printf("%q\n”, strings.Split(“a mountain a temple”, “a “)) fmt.Printf("%q\n”, strings.Split(” abc “, “”)) fmt.Printf("%q\n”, strings.Split(””, “oldboy”)) fmt.Println(“Fields 函数的用法”) fmt.Printf(“Fields are: %q\n”, strings.Fields(” Linux Python Golang Java “))}运行结果:Split 函数的用法[“Linux” “Python” “Golang” “Java”][”" “mountain " “temple”] [” " “a” “b” “c” " “][”"]Fields 函数的用法Fields are: [“Linux” “Python” “Golang” “Java”]