常用拼接方法

字符串拼接在日常开发中是很常见的需求,目前有两种普遍做法:

一种是直接用 += 来拼接

s1 := "Hello"
s2 := "World"
s3 := s1 + s2 // s3 == "HelloWorld"
s1 += s2 // s1 == "HelloWorld"

这是最常用也是最简单直观的方法,不过简单是有代价的,golang的字符串是不可变类型,也就是说每一次对字符串的“原地”修改都会重新生成一个string,再把数据复制进去,这样一来将会产生很可观的性能开销,稍后的性能测试中将会看到这一点。

第二种是使用bytes.Buffer

// bytes.Buffer的0值可以直接使用
var buff bytes.Buffer // 向buff中写入字符/字符串
buff.Write([]byte("Hello"))
buff.WriteByte(' ')
buff.WriteString("World") // String() 方法获得拼接的字符串
buff.String() // "Hello World"

这种方法用于需要大量进行字符串拼接操作的场合,性能要大大优于第一种方法。

不过使用bytes模块来操作string难免让人产生迷惑,所以在go1.10中新增了第三种方法:strings.Builder,官方鼓励尽量在string的拼接时使用Builder,byte拼接时使用Buffer

// strings.Builder的0值可以直接使用
var builder strings.Builder // 向builder中写入字符/字符串
builder.Write([]byte("Hello"))
builder.WriteByte(' ')
builder.WriteString("World") // String() 方法获得拼接的字符串
builder.String() // "Hello World"

从上面的代码中可以看到,strings.Builder和bytes.Buffer的操作几乎一样,不过strings.Builder仅仅实现了write类方法,而Buffer是可读可写的。

所以strings.Builder仅用于拼接/构建字符串

性能

除了是否易用外,另一条参考标准就是性能,得益于golang自带的测试工具,我们可以大致对比一下三种方案的性能。

测试使用从26个大写和小写字母10个数字以及5个常用符号共67字符中随机取10个组成string或[]byte,再由Buffer和Builder进行拼接。

先上测试结果

go test -bench=. -benchmem

下面是测试代码

// BenchmarkSpliceAddString10 测试使用 += 拼接N次长度为10的字符串
func BenchmarkSpliceAddString10(b *testing.B) {
s := ""
for i := ; i < b.N; i++ {
s += GenRandString()
}
} // BenchmarkSpliceBuilderString10 测试使用strings.Builder拼接N次长度为10的字符串
func BenchmarkSpliceBuilderString10(b *testing.B) {
var builder strings.Builder
for i := ; i < b.N; i++ {
builder.WriteString(GenRandString())
}
} // BenchmarkSpliceBufferString10 测试使用bytes.Buffer拼接N次长度为10的字符串
func BenchmarkSpliceBufferString10(b *testing.B) {
var buff bytes.Buffer
for i := ; i < b.N; i++ {
buff.WriteString(GenRandString())
}
} // BenchmarkSpliceBufferByte10 测试使用bytes.Buffer拼接N次长度为10的[]byte
func BenchmarkSpliceBufferByte10(b *testing.B) {
var buff bytes.Buffer
for i := ; i < b.N; i++ {
buff.Write(GenRandBytes())
}
} // BenchmarkSpliceBuilderByte10 测试使用string.Builder拼接N次长度为10的[]byte
func BenchmarkSpliceBuilderByte10(b *testing.B) {
var builder strings.Builder
for i := ; i < b.N; i++ {
builder.Write(GenRandBytes())
}
}

这是生成供拼接使用的随机字符串的代码(这里仍然使用了bytes.Buffer,推荐使用新的strings.Builder)

const (
data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890,.-=/"
) func init() {
rand.Seed(time.Now().Unix()) // 设置随机种子
} // GenRandString 生成n个随机字符的string
func GenRandString(n int) string {
max := len(data)
var buf bytes.Buffer
for i := ; i < n; i++ {
buf.WriteByte(data[rand.Intn(max)])
} return buf.String()
} // GenRandBytes 生成n个随机字符的[]byte
func GenRandBytes(n int) []byte {
max := len(data)
buf := make([]byte, n)
for i := ; i < n; i++ {
buf[i] = data[rand.Intn(max)]
} return buf
}

使用 += 的方法性能是最慢的,性能和其他两种差了好几个数量级。

Buffer和Builder性能相差无几,Builder在内存的使用上要略优于Buffer

结论

strings.Builder在golang 1.10才引入标准库的,所以 version <= 1.9 的时候对于大量字符串的拼接操作推荐bytes.Buffer

如果你正在使用1.10+,那么建议使用strings.Builder,不仅是更好的性能,也是为了能使代码更清晰。

当然,对于简单的拼接,+= 就足够了

golang的字符串拼接的更多相关文章

  1. golang 高效字符串拼接

    https://blog.csdn.net/u012210379/article/details/45110705 虽然方便,但是使用+=操作符并不是在一个循环中往字符串末尾追加字符串最有效的方式,一 ...

  2. [Golang]字符串拼接方式的性能分析

    本文100%由本人(Haoxiang Ma)原创,如需转载请注明出处. 本文写于2019/02/16,基于Go 1.11.至于其他版本的Go SDK,如有出入请自行查阅其他资料. Overview 写 ...

  3. golang中的字符串拼接

    go语言中支持的字符串拼接的方法有很多种,这里就来罗列一下 常用的字符串拼接方法 1.最常用的方法肯定是 + 连接两个字符串.这与python类似,不过由于golang中的字符串是不可变的类型,因此用 ...

  4. Golang拼接字符串的5种方法及其效率_Chrispink-CSDN博客_golang 字符串拼接效率 https://blog.csdn.net/m0_37422289/article/details/103362740

    Different ways to concatenate two strings in Golang - GeeksforGeeks https://www.geeksforgeeks.org/di ...

  5. golang字符串拼接

    四种拼接方案: 1,直接用 += 操作符, 直接将多个字符串拼接. 最直观的方法, 不过当数据量非常大时用这种拼接访求是非常低效的. 2,直接用 + 操作符,这个和+=其实一个意思了. 3,用字符串切 ...

  6. golang字符串拼接性能对比

    对比 +(运算符).strings.Join.sprintf.bytes.Buffer对字符串拼接的性能 package main import ( "bytes" "f ...

  7. Golang 入门 : 字符串

    在 Golang 中,字符串是一种基本类型,这一点和 C 语言不同.C 语言没有原生的字符串类型,而是使用字符数组来表示字符串,并以字符指针来传递字符串.Golang 中的字符串是一个不可改变的 UT ...

  8. Golang通过反射拼接一个结构体所有字段

    golang通过反射拼接一个结构体所有字段 需求 将一个结构体所有字段以"|"连接拼接成字符串 golang 不同类型拼接成string使用Sprintf比较麻烦,如果一个结构体有 ...

  9. SQL中字符串拼接

    1. 概述 在SQL语句中经常需要进行字符串拼接,以sqlserver,oracle,mysql三种数据库为例,因为这三种数据库具有代表性. sqlserver: select '123'+'456' ...

随机推荐

  1. win7里linux虚拟机安装vmware tools(ubuntu12.04)

    安装Vmware Tools工具 1.安装linux虚拟机(略) 2.虚拟机去启动,选择虚拟机à设置,“硬件”中选择CD/DVD(IDE),右侧选择“使用ISO镜像文件(M)”  -- 文件选择vmw ...

  2. ‘params’一个奇妙的东西

    params关键字表示函数的参数是可变个数的,即可变的方法参数,例如Console.WriteLine( "{0},{1} ",i,j); 就像DELPHI 里 WRITELN 函 ...

  3. 解决windows server在关闭远程桌面后开启的服务也随之关闭的问题

    首先远程登录服务器,关闭所有tomcat进程以及所有java进程,使用 netstat命令检查tomcat端口是否仍在监听状态,如仍在监听,使用taskkill杀死进程, 接下来关闭系统tomcat服 ...

  4. django 图书管理系统

    一.图书管理系统 单表的增删改查 1.创建项目 2.注释掉中间件 就可以提交post 请求 3.配置静态文件 并手动创建static 文件夹存放静态文件  二.具体的数据库配置 1.创建数据库  2. ...

  5. java 基础复习

    最近准备阿里巴巴的面试,被提到需要一个比较好的java能力,因此花了点时间,再次把JAVA看了一遍,其中的某些重点记录下来,以便以后复习. (1)& 和&& 的区别 (2)排序 ...

  6. RabbitMQ 使用主题进行消息分发

    在上篇文章RabbitMQ消息队列(五):Routing 消息路由 中,我们实现了一个简单的日志系统.Consumer可以监听不同severity的log.但是,这也是它之所以叫做简单日志系统的原因, ...

  7. 【转载】row cache lock

    转自:http://blog.itpub.net/26736162/viewspace-2139754/   定位的办法: --查询row cache lock等待 select event,p1   ...

  8. 友链 & 日记

    友链 & 日记 关于 \(Owen\) 温州中学初三 \(OIer\),目前 \(OI\) 水平一般,文化课成绩浮在中游.喜欢二次元,喜欢听音乐,标准宅一枚.虽然入宅时间很短 欢迎大家跟 \( ...

  9. Go语言结构

    目录 结构体定义 创建结构体实例 普通方式创建结构体实例 new()创建结构体实例 结构体实例初始化 结构体类型实例和指向它的指针内存布局 结构体的方法 面向对象 组合(继承) 结构体使用注意事项 G ...

  10. JVM内存分配和垃圾收集策略

    java内存区域 程序计数器 因为java可以多线程并发执行,因此,为了线程切换后能恢复到正确的执行位置,每个线程都需要一个独立的程序计数器.记录正在执行的虚拟机字节码指令的地址. 这个区域不会产生内 ...