在GO中字符串作为基本的类型,和c语言不同,c没有原生的字符串类型,c语言使用的是字符数组来表示字符串,并以字符指针来传递字符串。
1.字符串的表示
在Go语言中,字符串的值是不可变的,当创建一个字符串之后,无法再修改这个字符串内容,在GO中字符串是一个定长字符数组。
package mainimport ("fmt"
)var (value1 float64
)func main() {s := "aA你2"fmt.Println("字符串长度:", len(s))for i := 0; i < len(s); i++ {fmt.Println(s[i])}//结果是:字符串长度: 6
97 //a
65 //A
228 //你
189 //你
160 //你
50 //2/* 下面代码会报错,字符串能不值不能修改*/// s := "你好,"// t := ss += "世界。" //字符串可以连接,但原字符不会改变fmt.Println(s)//aA你2世界。}
非解释字符串
func main() {str1 := `苟利国家生死以,\n岂因祸福避趋之` //注意!键盘tab上门那个 ~ 的按键的点str2 := "今天天气\n真好"fmt.Println(str1)fmt.Println(str2)
}结果:苟利国家生死以,\n岂因祸福避趋之
今天天气
真好
注意上面的反单引号和双引号区别,首先单引号可以跨行,并且引号内的所有内容都会直接输出,包括转义字符换行,而双引号不能换行,且会解析转义字符。
操作字符串
func main() {s := "abcd你"fmt.Println(len(s)) // 长度7for i := 0; i < len(s); i++ {fmt.Println(s[i])}/* 输出 971009998228189160 *//*从上面字符串能看到汉字占3个字节,一共7个字节长度 */// c := s[len(s)]// fmt.Println(len(s), c)/*这两行代码会报错,因为字符串没有这个索引值(从0开始算,长度是7,但是最后一个字节索引是6)*/fmt.Println(s[0:7]) //s[0:7] 表示基于s字符串的第0个字节开始到第7字节(不包含第7个)生成一个新的字符串。生成的新字符串将包含7-0字节。也就是说如果要截取字符串,需要注意并不包含最后的那个字符。fmt.Println(s[4:]) //返回 :你fmt.Println(s[:3]) //返回 :adcfmt.Println(s[:4]) //返回 :abcdfmt.Println(s[:5]) //返回不出来 你 字 返回的是:abcd�fmt.Println(s[3:]) //返回 :d你
}
连接字符串
func main() {s := "abcd你"fmt.Println(s[4:] + "好") //你好fmt.Println(s[3:] + "好") //d你好str := "你好," + "Go!" //由于编译器自动加分号的原因,加号必须放在第一行fmt.Println(str) //你好,Go!
}
字符串遍历
func main() {s := "我是一个中国人"for i := 0; i < len(s); i++ {fmt.Printf("%c", s[i])fmt.Printf("%d=%v\n", i, s[i]) //输出单字节值}fmt.Printf("\n")
//使用这种方法无法输出我们想要的结果,因为单纯使用len方法是不能遍历字符串每个字符,只是遍历其一个字节是无法显示完成的字符串,因此遍历字符串要用range方式// For-each range 循环 这种格式的循环可以对字符串、数组、切片等进行迭代输出元素。for _, v := range s {fmt.Printf("%c", v)}//输出:我是一个中国人fmt.Printf("\n")t := []int{1, 2, 3, 4}for x, y := range t {fmt.Println(x, y)}
//其中x是键,y是值 类似键值对输出 输出: 0 11 22 33 4
}
字符串的修改
因为Go中字符串不能修改,也就是不能用s[i]的方式修改字符串的UTF-8编码,如果确实要修改
可以将字符串内容复制到另一个可写变量中,然后修改,一般用[]byte和[]rune格式,如果字符中的字节进行修改,则转换为[]rune格式,转换过程会自动复制数据
//[]byte格式
func main() { s := "hello 世界"b := []byte(s) //转换为[]byte,自动复制数据b[5] = ',' //修改[]bytefmt.Printf("%s\n", s)fmt.Printf("%s\n", b)}
输出:hello 世界hello,世界//[]rune格式
func main() { s := "hello 世界"r := []rune(s) //转换为[]rune,自动复制数据r[6] = '中' //修改[]runer[7] = '国'fmt.Println(s) //s不能被修改fmt.Println(string(r)) //转换为字符串,又一次复制数据
}输出:hello 世界hello 中国
包含判断(前后缀包含)
对于基本类型来说,字符串执行操作会比较复杂, Go语言标准库中有一个名为strings的库
package mainimport ("fmt""strings" //stings包
)var (value12 float64
)func main() {str := "This is an example of a string"fmt.Printf("Dose the string \"%s\" have have prftix %s?", str, "Th")fmt.Printf("\n")fmt.Printf("%t\n", strings.HasPrefix(str, "Th")) //HasPrefix判断前缀是否包含指定字符串fmt.Printf("%t\n", strings.HasSuffix(str, "string")) //HasSuffix判断后缀是否包含指定字符串fmt.Printf("%t\n", strings.Contains(str, "example")) //contains 判断是否包含指定字符串fmt.Println(strings.Contains("foo", "")) //turefmt.Println(strings.ContainsAny("foo", "")) //false//Contains和ContainsAny不同的点在于,第二个能够匹配更广泛的内容,它可以容纳Unicode字符}返回结果:
Dose the string "This is an example of a string" have have prftix Th?
true
true
true
true
false
索引
在strings包中Index就可以返回指定字符/串的第一个字符索引值,如果不存在相应的字符串,则返回-1。
func main() {str := "Hi, I'm Job, Hi."fmt.Printf("%d\n", strings.Index(str, "J")) // 8fmt.Printf("%d\n", strings.Index(str, "H")) // 0fmt.Printf("%d\n", strings.Index(str, "Fuck")) //-1
}
非ascll编码字符可以用IndexRune函数对字符进行定位
func main() {str := "我是张三"fmt.Printf("%d\n", strings.IndexRune(str, '张')) //6
}
替换
替换字符串最常用的方法是用正则匹配去替换,灵活度更高,但是Go语言对于比较基础的字符串替换已经打包在strings中了,例如:Replace函数
func main() {str := "我是张三"new := "李四"old := "张三"n := 1fmt.Println(strings.Replace(str, old, new, n)) /*其中n参数表示匹配到第几个old,如果n为-1则代表匹配所有*/
}结果:我是李四
统计
func main() {str := "Golang is cool, right?"var many0 = "o"fmt.Printf("%d\n", strings.Count(str, many0)) // o 出现3次fmt.Printf("%d\n", strings.Count(str, "oo")) // oo 出现1次}
结果:
3
1
字符数量
func main() {str := "你好世界"/*len([]rune(str))是两个方法的组合,先把字符串通过[]rune转化,然后统计长度*/fmt.Printf("%d\n", len([]rune(str)))/* 第二个方法是通过utf8包中的RuneCountInString函数统计,一般更推荐第二种,如果没有用utf8其他的函数可以没必要用这种方法用第一种也可以*/fmt.Println(utf8.RuneCountInString(str))}结果:
4
4
大小写转化
var (lower stringupper string
)func main() {str := "How are you?"fmt.Printf("%s\n", str)fmt.Printf("%s\n", strings.ToLower(str)) //ToLower转化成小写fmt.Printf("%s\n", strings.ToUpper(str)) //ToUpper转化成大写
}结果:
How are you?
how are you?
HOW ARE YOU?
修剪
func main() {str := "!!! Go !!!"fmt.Printf("%q\n", strings.Trim(str, "! "))fmt.Printf("%q\n", strings.Trim(str, " ! "))fmt.Printf("%q\n", strings.Trim(str, "!")) //注意第二个参数区别会造成什么结果str1 := "女朋友是最美的"fmt.Printf("%q\n", strings.Trim(str1, "女"))fmt.Printf("%q\n", strings.Trim(str1, "的"))fmt.Printf("%q\n", strings.Trim(str1, "女最")) //只减掉一个女字 最字没有减掉}结果:
"Go"
"Go"
" Go "
"朋友是最美的"
"女朋友是最美"
"朋友是最美的"
分割
func main() {fmt.Printf("%q\n", strings.Split("a,b,c", ","))fmt.Printf("%q\n", strings.Split("a boy a computer a pig", "a"))fmt.Printf("%q\n", strings.Split("qwe", ""))}结果:
["a" "b" "c"]
["" " boy " " computer " " pig"]
["q" "w" "e"]
插入
func main() {str := "The quick brown fox jumps over the lazy dog 厉害"strSli := strings.Fields(str)//strings.Fields函数用于把字符串转换为字符串切片,然后听过range获得每个切片的值,最后使用string.Join向字符串插入指定字符,除此之外还能使用字节缓冲bytes.Buffer连接字符串fmt.Printf("%s\n", strSli)for _, val := range strSli {fmt.Printf("%s ", val)}fmt.Println() //换行str2 := strings.Join(strSli, ";")fmt.Printf("%s\n", str2)
}结果:
[The quick brown fox jumps over the lazy dog 厉害]
The quick brown fox jumps over the lazy dog 厉害
The;quick;brown;fox;jumps;over;the;lazy;dog;厉害