Go 字符串使用
Go语言中的字符串
Go 中的字符串是兼容 Unicode 编码的,并且使用 UTF-8 进行编码,这样每一个Unicode字符根据代码点的大小使用1、2、3或4个字节表示代码点。
Go 语言中的字符串是一个字节切片,也就是说单个字符可以被字节索引,我们可以假定每个字符的编码只会占用一个字节。例如:
1 2 3 4 | var s = "Hello world!" for i:= 0; i < len(s); i++ { fmt.Printf( "%x " , s[i]) //48 65 6c 6c 6f 20 77 6f 72 6c 64 21 } |
如果是ASCII字符(用一个单一的UTF-8字节表示)(一个字节),这样做没有什么问题,若是非ASCII字符?。
对于每一个Unicode字符呢,占用的字节大小不一样,可是我们怎么知道每次取多少个字节的大小?
所以在Go语言中,我可以使用rune来解决这个问题,不管这个字符占多大的字节,都可以用一个rune来表示。
rune 是 Go 语言的内建类型,它也是 int32 的别称。在 Go 语言中,rune 表示一个代码点。
1 2 3 4 5 6 7 8 9 10 | package main import "fmt" func main() { var s = "Hello world!" runes := []rune(s) for i:= 0; i < len(runes); i++ { fmt.Printf( "%c " ,runes[i]) } //H e l l o w o r l d ! } |
注:https://naveenr.net/unicode-character-set-and-utf-8-utf-16-utf-32-encoding/ 来理解一下什么是 Unicode 和 UTF-8。
字符串的构造
- 用字节切片构造字符串
- 用 rune 切片构造字符串
用字节切片构造字符串
byteSlice
包含字符串 Café
用 UTF-8 编码后的 16 进制字节
1 2 3 4 5 6 7 8 9 10 | 用字节切片构造字符串 package main import ( "fmt" ) func main() { byteSlice := []byte{0x43, 0x61, 0x66, 0xC3, 0xA9} str := string(byteSlice) fmt.Println(str) //Café} |
用 rune 切片构造字符串
runeSlice
包含字符串 Señor
的 16 进制的 Unicode 代码点
1 2 3 4 5 6 7 8 9 | package main import ( "fmt" ) func main() { runeSlice := []rune{0x0053, 0x0065, 0x00f1, 0x006f, 0x0072} str := string(runeSlice) fmt.Println(str) //Café} |
字符串切片处理
1 2 3 4 5 6 7 | func main() { //字符串底层是一个byte数组,可以做切片处理 str := "hello world!" //使用切片 slice := str[2:] fmt.Println( "slice=" ,slice) //slice= llo world! } |
字符串长度
获取字符串的字节数:len(str)
方法返回包含在字符串文字中的字节数。
1 2 3 4 5 6 7 | package main import "fmt" func main() { var greeting = "Hello world!" fmt.Printf( "String Length is: " ) fmt.Println(len(greeting)) //String Length is : 12} |
获取字符串的字符个数:utf8 package 包中的 func RuneCountInString(s string) (n int)
方法用来获取字符串的长度。这个方法传入一个字符串参数然后返回字符串中的 rune 的数量。
1 2 3 4 5 6 7 8 9 10 11 12 13 | package main import ( "fmt" "unicode/utf8" ) func length(s string) { fmt.Printf( "length of %s is %d\n" , s, utf8.RuneCountInString(s))} func main() { word1 := "Señor" length(word1) //length of Señor is 5 word2 := "Pets" length(word2) //length of Señor is 4 } |
字符串的迭代
字符串的迭代有两种方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package main import ( "fmt" ) <br> //方法1,使用for range func printChars1(s string) { for index, rune := range s { fmt.Printf( "%c starts at byte %d\n" , rune, index) } } <br> //方法2 func printChars2(s string) { runes := []rune(s) for i:= 0; i < len(runes); i++ { fmt.Printf( "%c " , runes[i]) } } func main() { name := "Señor" printChars1(name) printChars2(name) } |
输出结果:
1 2 3 4 5 6 | S starts at byte 0 e starts at byte 1 ñ starts at byte 2 o starts at byte 4 r starts at byte 5 S e ñ o r |
字符串不可变
string 是不可变的,也就说不能通过 str[0] = 'w' 方式来修改字符串。
如果需要修改字符串,可以先将 string -> []byte 或者 []rune -> 修改 -> 重写转成 string1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package main import "fmt" func main() { //字符串底层是一个byte数组,可以做切片处理 str := "zello world!" arr1 := []byte(str) arr1[0] = 'h' str = string(arr1) fmt.Println( "str=" ,str) //转换成byte后,可以处理英文和数字,不能处理中文 //[]byte一个索引只能处理一个字节的数据,汉字超出范围,会出现乱码 //前面我们提到[]rune能将所有字符用一个字节表示 arr2 := []rune(str) arr2[0] = '一' str = string(arr2) fmt.Println( "str=" ,str) } |
1 2 3 | 结果: str= hello world! str= 一ello world! |
连接字符串
strings
包包含一个用于连接多个字符串的join()
方法,其语法如下:
1 | strings.Join(sample, " " ) |
Join
连接数组的元素以创建单个字符串。第二个参数是分隔符,放置在数组的元素之间。
1 2 3 4 5 6 7 8 | package main import ( "fmt" "strings" ) func main() { greetings := []string{ "Hello" , "world!" } fmt.Println(strings.Join(greetings, " " )) //Hello world!} |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
2018-11-05 Web侦察工具HTTrack (爬取整站)
2018-11-05 文件上传漏洞绕过技巧