Go语言中的字符串拼接方法详情
来源:脚本之家
时间:2023-01-09 09:27:07 493浏览 收藏
在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Go语言中的字符串拼接方法详情》,聊聊语言字符串、拼接,希望可以帮助到正在努力赚钱的你。
1、string类型
string
类型的值可以拆分为一个包含多个字符(rune类型)的序列,也可以被拆分为一个包含多个字节 (byte类型) 的序列。其中一个rune
类型值代表一个Unicode
字符,一个rune
类型值占用四个字节,底层就是一个 UTF-8 编码值,它其实是int32类型的一个别名类型。
package main import ( "fmt" ) func main() { str := "你好world" fmt.Printf("The string: %q\n", str) fmt.Printf("runes(char): %q\n", []rune(str)) fmt.Printf("runes(hex): %x\n", []rune(str)) fmt.Printf("bytes(hex): [% x]\n", []byte(str)) }
执行结果:
The string: "你好world"
runes(char): ['你' '好' 'w' 'o' 'r' 'l' 'd']
runes(hex): [4f60 597d 77 6f 72 6c 64]
bytes(hex): e4 bd a0 e5 a5 bd 77 6f 72 6c 64
可以看到,英文字符使用一个字节,而中文字符需要三个字节。下面使用 for range
语句对上面的字符串进行遍历:
for index, value := range str { fmt.Printf("%d: %q [% x]\n", index, value, []byte(string(value))) }
执行结果如下:
0: '你' [e4 bd a0]
3: '好' [e5 a5 bd]
6: 'w' [77]
7: 'o' [6f]
8: 'r' [72]
9: 'l' [6c]
10: 'd' [64]
index
索引值不是0-6,相邻Unicode
字符的索引值不一定是连续的,因为中文字符占用了3个字节,宽度为3。
2、strings包
2.1 strings.Builder类型
strings.Builder
的优势主要体现在字符串拼接上,相比使用+拼接,效率更高。
strings.Builder
已存在的值不可改变,只能重置(Reset()
方法)或者拼接更多的内容。- 一旦调用了
Builder
值,就不能再以任何方式对其进行复制,比如函数间值传递、通道传递值、把值赋予变量等。 - 在进行拼接时,
Builder
值会自动地对自身的内容容器进行扩容,也可以使用Grow
方法进行手动扩容。
package main import ( "fmt" "strings" ) func main() { var builder1 strings.Builder builder1.WriteString("hello") builder1.WriteByte(' ') builder1.WriteString("world") builder1.Write([]byte{' ', '!'}) fmt.Println(builder1.String()) f1 := func(b strings.Builder) { // b.WriteString("world !") //会报错 } f1(builder1) builder1.Reset() fmt.Printf("The length 0f builder1: %d\n", builder1.Len()) }
执行结果:
hello world !
The length 0f builder1: 0
2.2 strings.Reader类型
strings.Reader
类型可以用于高效地读取字符串,它通过使用已读计数机制来实现了高效读取,已读计数保存了已读取的字节数,也代表了下一次读取的起始索引位置。
package main import ( "fmt" "strings" ) func main() { reader1 := strings.NewReader("hello world!") buf1 := make([]byte, 6) fmt.Printf("reading index: %d\n", reader1.Size()-int64(reader1.Len())) reader1.Read(buf1) fmt.Println(string(buf1)) fmt.Printf("reading index: %d\n", reader1.Size()-int64(reader1.Len())) reader1.Read(buf1) fmt.Println(string(buf1)) fmt.Printf("reading index: %d\n", reader1.Size()-int64(reader1.Len())) }
执行结果:
reading index: 0
hello
reading index: 6
world!
reading index: 12
可以看到,每读取一次之后,已读计数就会增加。
strings
包的ReadAt
方法不会依据已读计数进行读取,也不会更新已读计数。它可以根据偏移量来自由地读取Reader
值中的内容。
package main import ( "fmt" "strings" ) func main() { reader1 := strings.NewReader("hello world!") buf1 := make([]byte, 6) offset1 := int64(6) n, _ := reader1.ReadAt(buf1, offset1) fmt.Println(string(buf2)) }
执行结果:
world!
也可以使用Seek
方法来指定下一次读取的起始索引位置。
package main import ( "fmt" "strings" "io" ) func main() { reader1 := strings.NewReader("hello world!") buf1 := make([]byte, 6) offset1 := int64(6) readingIndex, _ := reader2.Seek(offset1, io.SeekCurrent) fmt.Printf("reading index: %d\n", readingIndex) reader1.Read(buf1) fmt.Printf("reading index: %d\n", reader1.Size()-int64(reader1.Len())) fmt.Println(string(buf1)) }
执行结果:
reading index: 6
reading index: 12
world!
3、bytes.Buffer
bytes
包和strings
包类似,strings
包主要面向的是 Unicode
字符和经过 UTF-8 编码的字符串,而bytes
包面对的则主要是字节和字节切片,主要作为字节序列的缓冲区。bytes.Buffer
数据的读写都使用到了已读计数。
bytes.Buffer
具有读和写功能,下面分别介绍他们的简单使用方法。
3.1 bytes.Buffer:写数据
和strings.Builder
一样,bytes.Buffer
可以用于拼接字符串,strings.Builder
也会自动对内容容器进行扩容。请看下面的代码:
package main import ( "bytes" "fmt" ) func DemoBytes() { var buffer bytes.Buffer buffer.WriteString("hello ") buffer.WriteString("world !") fmt.Println(buffer.String()) }
执行结果:
hello world !
3.2 bytes.Buffer:读数据
bytes.Buffer
读数据也使用了已读计数,需要注意的是,进行读取操作后,Len
方法返回的是未读内容的长度。下面直接来看代码:
package main import ( "bytes" "fmt" ) func DemoBytes() { var buffer bytes.Buffer buffer.WriteString("hello ") buffer.WriteString("world !") p1 := make([]byte, 5) n, _ := buffer.Read(p1) fmt.Println(string(p1)) fmt.Println(buffer.String()) fmt.Printf("The length of buffer: %d\n", buffer.Len()) }
执行结果:
hello
world !
The length of buffer: 8
4、字符串拼接
简单了解了string类型、strings包和bytes.Buffer类型后,下面来介绍golang中的字符串拼接方法。
https://zhuanlan.zhihu.com/p/349672248
go test -bench=. -run=^BenchmarkDemoBytes$
4.1 直接相加
最简单的方法是直接相加,由于string类型的值是不可变的,进行字符串拼接时会生成新的字符串,将拼接的字符串依次拷贝到一个新的连续内存空间中。如果存在大量字符串拼接操作,使用这种方法非常消耗内存。
package main import ( "bytes" "fmt" "time" ) func main() { str1 := "hello " str2 := "world !" str3 := str1 + str2 fmt.Println(str3) }
4.2strings.Builder
前面介绍了strings.Builder
可以用于拼接字符串:
var builder1 strings.Builder builder1.WriteString("hello ") builder1.WriteString("world !")
4.3 strings.Join()
也可以使用strings.Join
方法,其实Join()
调用了WriteString
方法;
str1 := "hello " str2 := "world !" str3 := "" str3 = strings.Join([]string{str3,str1},"") str3 = strings.Join([]string{str3,str2},"")
4.4 bytes.Buffer
bytes.Buffer也可以用于拼接:
var buffer bytes.Buffer buffer.WriteString("hello ") buffer.WriteString("world !")
4.5 append方法
也可以使用Go
内置函数append
方法,用于拼接切片:
package main import ( "fmt" ) func DemoAppend(n int) { str1 := "hello " str2 := "world !" var str3 []byte str3 = append(str3, []byte(str1)...) str3 = append(str3, []byte(str2)...) fmt.Println(string(str3)) }
执行结果:
hello world !
4.6 fmt.Sprintf
fmt
包中的Sprintf
方法也可以用来拼接字符串:
str1 := "hello " str2 := "world !" str3 := fmt.Sprintf("%s%s", str1, str2)
5、字符串拼接性能测试
下面来测试一下这6种方法的性能,编写测试源码文件strcat_test.go
:
package benchmark import ( "bytes" "fmt" "strings" "testing" ) func DemoBytesBuffer(n int) { var buffer bytes.Buffer for i := 0; i通过平均耗时可以看到
WriteString
方法执行效率最高。Sprintf
方法效率最低。
- 我们看到
Strings.Join
方法效率也比较低,在上面的场景下它的效率比较低,它在合并已有字符串数组的场合效率是很高的。 - 如果要连续拼接大量字符串推荐使用
WriteString
方法,如果是少量字符串拼接,也可以直接使用+。 append
方法的效率也是很高的,它主要用于切片的拼接。fmt.Sprintf
方法虽然效率低,但在少量数据拼接中,如果你想拼接其它数据类型,使用它可以完美的解决:
name := "zhangsan" age := 20 str4 := fmt.Sprintf("%s is %d years old", name, age) fmt.Println(str4) // zhangsan is 20 years old
到这里,我们也就讲完了《Go语言中的字符串拼接方法详情》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于golang的知识点!
-
213 收藏
-
218 收藏
-
402 收藏
-
303 收藏
-
281 收藏
-
377 收藏
-
384 收藏
-
246 收藏
-
110 收藏
-
210 收藏
-
108 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习