1.1 什么是string
Go中的字符串是一个字节的切片。可以通过将其内容封装在””中来创建字符串。Go中的字符是Unicode兼容的,并且是utf-8编码,判断长度和输出要考虑兼容性。
Go与Java语言一样,字符串默认是不可变的,保证了线程安全,使用的都是只读对象,无需加锁,且很方便共享内存,不必使用写时复制。
1.2 string基础语法
1.2.1 字符串和字符
Go没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存,且使用单引号包裹
var c1 = 'A'var c2 byte = 'B'c3 := 'C'fmt.Println("c1,c2,c3 :", c1, c2, c3)fmt.Printf("c1=%c,c2=%c,c3=%c\n", c1, c2, c3)c4 := '我'c5 := '1'fmt.Println("c4,c5 :", c4, c5)fmt.Printf("c4=%c,c5=%c\n", c4, c5)/*c1,c2,c3: 65 66 67c1=A,c2=B,c3=Cc4,c5: 25105 49c4=我,c5=1*/
1.2.2 定义与修改
Go的修改不能直接修改比如str[1]=”e”,这种改法是错误的,需要转成byte[]进行转换
// 定义str := "Test测试"fmt.Println("修改前的str:", str)strTemp := []byte(str)strTemp[2] = 'e'str = string(strTemp)fmt.Println("修改后的str:", str)/*修改前的str: Test测试修改后的str: Teet测试*/
1.2.3 切割
Go中的切割使用很方便语法为:
arr[a:b] // 其中a是开始的索引,b是结束的索引,前闭后开a,b可以不写,a不写意为从头开始切,b不写意为切到尾
示例为:
strNum := "123456"fmt.Println(strNum[1:4])fmt.Println(strNum[1:])fmt.Println(strNum[:4])/*234234561234*/
1.2.4 获取长度
字符串获取长度,有以下的规则
- 如果是中文,那么使用utf8.RuneCountInString(str)
- 如果不是中文,使用utf8.RuneCountInString(str)和len(str)都可以 ```go strNum := “123456” strWord := “hello” strChinese := “你好世界” strChineseAndWord := “hello世界” strChineseAndNum := “世界123” fmt.Println(len(strNum), len(strWord), len(strChinese), len(strChineseAndWord), len(strChineseAndNum))
fmt.Println(utf8.RuneCountInString(strNum), utf8.RuneCountInString(strWord), utf8.RuneCountInString(strChinese), utf8.RuneCountInString(strChineseAndWord), utf8.RuneCountInString(strChineseAndNum)) / 6 5 12 11 9 6 5 4 7 5 /
> 总结:为了避免出现异常和统一性,推荐使用utf8.RuneCountInString_(str_)获取长度;<a name="HDKft"></a>### 1.2.5 字符串遍历字符串的遍历有两种方式,一种是通过长度 for i;i<len();i++,一种是通过range,注意区分中文和非中文<br />示例一、遍历非中文:```gos1 := "hello"// 遍历方式一for i := 0; i < len(s1); i++ {fmt.Printf(" %c\n", s1[i])}fmt.Println("---------------")// 遍历方式二for i, ch := range s1 {fmt.Printf(" 索引是%d,字符为%c\n", i, ch)}/*hello---------------索引是0,字符为h索引是1,字符为e索引是2,字符为l索引是3,字符为l索引是4,字符为o*/
示例二、遍历中文
s2 := "你好世界"// 遍历方式一for i := 0; i < utf8.RuneCountInString(s2); i++ {fmt.Printf("%c\n", s2[i])}fmt.Println("----------------")// 遍历方式二for i, ch := range s2 {fmt.Printf("索引是%d,字符为%c\n", i, ch)}/*ä½å----------------索引是0,字符为你索引是3,字符为好索引是6,字符为世索引是9,字符为界*/
总结:为了避免出现异常和统一性,推荐使用range进行遍历;
1.2.6 字符串拼接
使用’+’能够连接字符串,但是该操作并不高效(因为字符串在go中是基本类型,每次拼接都是拷贝了内存!)。
Go1.10提供了类似java的stringBuilder机制进行高效字符串拼接。
示例:(注意这里的示例需要引入’bytes’模块)
str1 := "hello "str2 := "world"fmt.Println(str1 + str2)// 创建字节缓冲var stringBuilder bytes.Buffer// 把字符串写入缓冲stringBuilder.WriteString(str1)stringBuilder.WriteString(str2)// 将缓冲以字符串形式输出fmt.Println(stringBuilder.String())/*hello worldhello world*/
1.2.7 strings库常用函数
这里仅仅是几个例子,还有很多可以自己调用测试。
内置的strings模块包含很多常用的方法,使用时,需要引入”strings”模块。
1.2.7.1 获取索引位置
str1 := "This my first step"// 获取索引位置var index = strings.Index(str1, "m")fmt.Printf("%v its index of 'm' is :%v\n", str1, index)/*This my first step its index of 'm' is :5*/
1.2.7.2 判断是否包含某个字符串
str1 := "This my first step"var contain = strings.Contains(str1, "fi")fmt.Printf("%v whether contain 'fi' :%v\n", str1, contain)/*This my first step whether contain 'fi' :true*/
1.2.7.3 替换字符串
// 替换字符串str中old字符串为新的字符串,n表示替换的次数,小于0全部替换str := "zzzledz"fmt.Println("replace once result :" + strings.Replace(str, "z", "b", 1)) // 替换1次str2 := "zzzledz"fmt.Println("replace second result :" + strings.Replace(str2, "z", "b", 2)) // 替换2次str3 := "zzzledz"fmt.Println("replace all result :" + strings.Replace(str3, "z", "b", -1)) //全部替换/*replace once result :bzzledzreplace second result :bbzledzreplace all result :bbbledb*/
1.2.7.4 切片(split)
// 字符串切片,返回的是一个[]sring字符串数组var strArr = strings.Split("one-two-three", "-")fmt.Println(strArr)/*[one two three]*/
1.2.7.5 去除头尾字符
- strings.Trim(s,str) 去除s字符串头尾部包含的str字符
- strings.TrimPrefix(s,str) 去除s字符串头部包含的str字符
- strings.TrimSuffix(s,str) 去除s字符串尾部包含的str字符
- strings.Fields(s) 去除s字符串的空白 ```go fmt.Println(strings.TrimPrefix(“zledHellozled”, “zled”)) // 去除头部空格 fmt.Println(strings.TrimSuffix(“zledHellozled”, “zled”)) // 去除头部 fmt.Println(strings.Trim(“zledHellozled”, “zled”)) // 去除尾部 var s = “ BCA D E “ fmt.Println(strings.Fields(s)) // 切割空格,返回[]string数组
/ Hellozled zledHello Hello [BCA D E] /
<a name="8bW9D"></a>#### 1.2.7.6 自定义拼接符(join)```govar obtStr = "ABC"obtArr := []string{"+","-","*","/"}fmt.Println(strings.Join(obtArr, obtStr))/*+ABC-ABC*ABC/*/
1.2.8 strconv库常用函数
1.2.8.1 字符串转换
如果只是转换类型,可以直接使用string(obt)将obt转成string类型
在java中遇到 “你好”+123 会将+转变为连接符,而Go语言要求,+号两边数据的类型必须一直,这使得类似的操作变得比较不便
Go提供了strconv包用于字符串与基本类型之间的转换,常用函数有Append,format,parse
// format系列函数把其他类型转换成字符串a := strconv.Itoa(13)b := strconv.FormatBool(false)// 要转换的浮点数,格式标记,精度(数字部分的长度,不包括指数部分),指定浮点类型(32:float32,64:float64)c := strconv.FormatFloat(123.23, 'g', 12, 64)// 将 int 型整数 i 转换为字符串形式,base:进位制(2 进制到 36 进制)d := strconv.FormatInt(1234, 10)e := strconv.FormatUint(12345, 10)fmt.Println(a + "哈哈" + b + c + d + e)/*13哈哈false123.23123412345*/
1.2.8.2 字符串拼接
strconv中也包含拼接函数,示例如下:
arr1 := make([]byte, 0, 100) // 返回的总长度是100,第二个参数是长度,第三个参数是用来指定预留的空间长度arr1 = strconv.AppendInt(arr1, 5467, 10)arr1 = strconv.AppendBool(arr1, false)arr1 = strconv.AppendQuote(arr1, "abcdefg")arr1 = strconv.AppendQuoteRune(arr1, '单')fmt.Println(string(arr1))/*5467false"abcdefg"'单'*/
1.3 string、rune、byte
有时在对特定的操作时,需要进行转换
- byte等同于int8,常用来处理ascii字符
- rune等同于int32,常用来处理unicode或utf-8字符
示例:
比如下面的,字符串反转
方法1,首先是最原始的写法:
str := "zled"func stringReverse(str string) string {split := strings.Split(str, "")for from, to := 0, len(split)-1; from < to; from, to = from+1, to-1 {split[from], split[to] = split[to], split[from]}return strings.Join(split, "")}fmt.Println("str 反转后的结果是:", stringReverse(str))/*str 反转后的结果是: delz*/
方法2,是使用rune代替一些操作
str := "zled"func stringReverse(str string) string {// 变量值交换runes := []rune(str)for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {runes[from], runes[to] = runes[to], runes[from]}return string(runes)}fmt.Println("str 反转后的结果是:", stringReverse(str))/*str 反转后的结果是: delz*/
可以看出使用rune省略了转换和合并的操作,所以有的时候操作string的时候可以转换为rune,然后再进行后续操作。
