字符串底层以及常用方法
1.1. 字符串
在编写程序时,使用字符串来进行文本的处理,例如:
package main
import "fmt"
func main() {
var name string = "alex"
fmt.Printf(name)
title := "生活要想过得去,头上总得带点绿"
fmt.Printf(title)
}
字符串的底层存储
计算机中所有的操作和数据最终都是二进制,即:1000100001011...
Go语言中的字符串是utf-8编码的序列。
package main
import "fmt"
func main() {
// unicode字符集:文字 -> 码点(ucs4, 4个字节表示)
// utf-8编码,对unicode字符集的码点进行编码最终得到:1000100001
var name string = "武沛齐"
fmt.Printf(name)
}
课上代码示例:
package main
import (
"fmt"
"strconv"
"unicode/utf8"
)
func main() {
// 1. 本质是utf-8编码的序列
var name string = "武沛齐"
// 武 => 11100110 10101101 10100110
fmt.Println(name[0], strconv.FormatInt(int64(name[0]), 2))
fmt.Println(name[1], strconv.FormatInt(int64(name[1]), 2))
fmt.Println(name[2], strconv.FormatInt(int64(name[2]), 2))
// 武 => 11100110 10110010 10011011
fmt.Println(name[3], strconv.FormatInt(int64(name[3]), 2))
fmt.Println(name[4], strconv.FormatInt(int64(name[4]), 2))
fmt.Println(name[5], strconv.FormatInt(int64(name[5]), 2))
// 武 => 11101001 10111101 10010000
fmt.Println(name[6], strconv.FormatInt(int64(name[6]), 2))
fmt.Println(name[7], strconv.FormatInt(int64(name[7]), 2))
fmt.Println(name[8], strconv.FormatInt(int64(name[8]), 2))
// 2. 获取字符串的长度:9(字节长度)
fmt.Println(len(name))
// 3. 字符串转换为一个"字节集合"
byteSet := []byte(name)
fmt.Println(byteSet) // [230,173,166,230,178,155,233,189,144]
// 4. 字节的集合转换为字符串
byteList := []byte{230, 173, 166, 230, 178, 155, 233, 189, 144}
targetString := string(byteList)
fmt.Println(targetString)
// 5. 将字符串转换为 unicode字符集码点的集合 6b66 -> 武 6c9b->沛 9f50->齐
tempSet := []rune(name)
fmt.Println(tempSet) // [27494 27803 40784]
fmt.Println(tempSet[0], strconv.FormatInt(int64(tempSet[0]), 16))
fmt.Println(tempSet[1], strconv.FormatInt(int64(tempSet[1]), 16))
fmt.Println(tempSet[2], strconv.FormatInt(int64(tempSet[2]), 16))
// 6. "rune集合" 转换 为字符串
runeList := []rune{27494, 27803, 40784}
targetName := string(runeList)
fmt.Println(targetName)
// 7. 长度的处理(获取字符长度)
runeLength := utf8.RuneCountInString(name)
fmt.Println(runeLength)
}
字符串常见功能
字符串属于在程序中最常见用的数据类型,所以Go中为字符串提供了很多常见的操作。
1 获取长度
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
var name string = "武沛齐"
fmt.Println( len(name) ) // 获取 字节 长度,输出:8
fmt.Println( utf8.RuneCountInString(name) ) // 获取字符长度,输出:3
}
2 是否以xx开头
package main
import (
"fmt"
"strings"
)
func main() {
name := "武沛齐"
result := strings.HasPrefix(name, "武")
fmt.Println(result) // 输出:true
}
3 是否以xx结尾
package main
import (
"fmt"
"strings"
)
func main() {
name := "武沛齐"
result := strings.HasSuffix(name, "齐")
fmt.Println(result) // 输出:true
}
4 是否包含
package main
import (
"fmt"
"strings"
)
func main() {
name := "抬老子的意大利炮来"
result := strings.Contains(name, "老子")
fmt.Println(result) // 输出:true
}
5 变大写
package main
import (
"fmt"
"strings"
)
func main() {
name := "wupeiqi"
result := strings.ToUpper(name)
fmt.Println(result) // 输出:WUPEIQI
}
// 注意:result是大写;name依然是小写。
6 变小写
package main
import (
"fmt"
"strings"
)
func main() {
name := "WUPEIQI"
result := strings.ToLower(name)
fmt.Println(result) // 输出:wupeiqi
}
7 去两边
package main
import (
"fmt"
"strings"
)
func main() {
name := "wupeiqi"
result1 := strings.TrimRight(name, "qi") // 去除右边的qi
result2 := strings.TrimLeft(name, "w") // 去除左边的w
result3 := strings.Trim(name, "w") // 去除两边的w
fmt.Println(result1, result2, result3) // 输出:wupe upeiqi upeiqi
}
8 替换
package main
import (
"fmt"
"strings"
)
func main() {
name := "wupeipeiqi"
result1 := strings.Replace(name, "pei", "PE", 1) // 找到pei替换为PE,从左到右找第一个替换
result2 := strings.Replace(name, "pei", "PE", 2) // 找到pei替换为PE,从左到右找前两个替换
result3 := strings.Replace(name, "pei", "PE", -1) // 找到pei替换为PE,替换所有
fmt.Println(result1, result2, result3)
}
9 分割
package main
import (
"fmt"
"strings"
)
func main() {
name := "抬老子的意大利的炮来"
result := strings.Split(name, "的")
// 根据`的`进行切割,获取一个切片(类似于一个数组)
fmt.Println(result) // [ 抬老子, 意大利, 炮来 ]
}
10 拼接
可以使用 +
让两个字符串进行拼接,但这样的拼接效率会非常的低,不建议使用,建议大家使用以下的方式:
package main
import (
"bytes"
"fmt"
"strings"
)
func main() {
// 不建议
message := "我爱" + "北京天安门"
fmt.Println(message)
// 建议:效率高一些
dataList := []string{"我爱", "北京天安门"}
result := strings.Join(dataList, "")
fmt.Println(result) // 我爱北京天安门
// 建议:效率更高一些(go 1.10之前)
var buffer bytes.Buffer
buffer.WriteString("你想")
buffer.WriteString("我干")
buffer.WriteString("他")
data := buffer.String()
fmt.Print(data)
// 建议:效率更更更更高一些(go 1.10之后)
var builder strings.Builder
builder.WriteString("哈哈哈")
builder.WriteString("去你的吧")
value := builder.String()
fmt.Print(value)
}
11 string转换为int
package main
import (
"fmt"
"strconv"
)
func main() {
num := "666"
// 内部调用的就是 ParseInt
var data, _ = strconv.Atoi(num)
fmt.Println(data)
// 整型转字符串(strconv.ParseInt 和 strconv.FormatInt 可用处理进制转换)
// 十进制:整型; 其他进制:字符串形式
var result, err = strconv.ParseInt(num, 10, 32)
fmt.Println(result, err)
}
12 int转换为string
package main
import (
"fmt"
"strconv"
)
func main() {
var result = strconv.Itoa(888)
fmt.Println(result)
}
13 字符串 和 “字节集合”
package main
import (
"fmt"
"strconv"
"unicode/utf8"
)
func main() {
var name string = "武沛齐"
// 字符串转换为一个"字节集合"
byteSet := []byte(name)
fmt.Println(byteSet) // [230,173,166,230,178,155,233,189,144]
// 字节的集合转换为字符串
byteList := []byte{230, 173, 166, 230, 178, 155, 233, 189, 144}
targetString := string(byteList)
fmt.Println(targetString)
}
14 字符串 和 “rune集合”
package main
import (
"fmt"
"strconv"
"unicode/utf8"
)
func main() {
var name string = "武沛齐"
// 将字符串转换为 unicode字符集码点的集合 6b66 -> 武 6c9b->沛 9f50->齐
tempSet := []rune(name)
fmt.Println(tempSet) // [27494 27803 40784]
fmt.Println(tempSet[0], strconv.FormatInt(int64(tempSet[0]), 16))
fmt.Println(tempSet[1], strconv.FormatInt(int64(tempSet[1]), 16))
fmt.Println(tempSet[2], strconv.FormatInt(int64(tempSet[2]), 16))
// "rune集合" 转换 为字符串
runeList := []rune{27494, 27803, 40784}
targetName := string(runeList)
fmt.Println(targetName)
}
15 string 和 字符
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
// 数字转字符串
v1 := string(65)
fmt.Println(v1) // A
v2 := string(27494)
fmt.Println(v2) // 武
// 字符串转数字
v3, size := utf8.DecodeRuneInString("A")
fmt.Println(v3, size) // 65 1
v4, size := utf8.DecodeRuneInString("武")
fmt.Println(v4, size) // 27494 3
}
应用场景:生成一个随机数,然后调用string得到一个随机的字符。
索引切片和循环
package main
import "fmt"
func main() {
var name string = "武沛齐"
// 1. 索引获取字节
v1 := name[0]
fmt.Println(v1) // 230
// 2. 切片获取字节区间
v2 := name[0:3]
fmt.Println(v2) // 武
// 3. 手动循环获取所有字节
/*
0 230
1 173
2 166
3 230
4 178
5 155
6 233
7 189
8 144
*/
for i := 0; i < len(name); i++ {
fmt.Println(i, name[i])
}
// 4. for range 循环获取所有字符
/*
0 27494 武
3 27803 沛
6 40784 齐
*/
for index, item := range name {
fmt.Println(index, item, string(item))
}
// 5.转换成rune集合 [27494,27803,40784]
dataList := []rune(name)
fmt.Println(dataList[0], string(dataList[0]))
}