Go语言字符串拼接性能对比与最佳实践 - 深度优化指南

boyanx4个月前技术教程16


字符串拼接在日常开发中非常的常见,go 也有多种方式可以进行字符串拼接,但是当数据量足够大的情况下,不同的拼接方式会产生显著的性能差异。本文通过基准测试数据,带您深入理解Go语言字符串操作的底层机制,文末附结论:最终字符串拼接最优的方式

一、常用拼接方式

  • +号拼接
  • fmt 占位符
  • strings.Builder
  • bytes.Buffer

二、性能对比实验

package main
import (
"bytes"
"fmt"
"strings"
"testing"
)
const LOOP = 1000
// BenchmarkStringAdd + 号拼接
func BenchmarkStringAdd(b *testing.B) {
for n := 0; n < b.N; n++ {
var s string
for j := 0; j < LOOP; j++ {
s += "gopher"
}
}
}
//
BenchmarkStringBytesBufferAdd bytes.Buffer 拼接

func BenchmarkStringFmtAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
var s string
for j := 0; j < LOOP; j++ {
s = fmt.Sprintf("%sgopher", s)
}
}
}
// BenchmarkStringBuilderAdd strings.Builder 拼接
func BenchmarkStringBuilderAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
var builder strings.Builder
for j := 0; j < LOOP; j++ {
builder.WriteString("gopher")
}
_ = builder.String()
}
}
//
BenchmarkStringBytesBufferAdd bytes.Buffer 拼接

func
BenchmarkStringBytesBufferAdd(b *testing.B) {

for i := 0; i < b.N; i++ {
var builder bytes.Buffer
for j := 0; j < LOOP; j++ {
builder.WriteString("gopher")
}
_ = builder.String()
}
}

执行测试:

# go test -bench='BenchmarkStringBuilderAdd' -cpu=2 -count=1 -benchmem .
BenchmarkStringBuilderAdd-2 259993 4663 ns/op 24824 B/op 14 allocs/op
PASS
ok learn-go 4.600s
# go test -bench='BenchmarkStringFmtAdd' -cpu=2 -count=1 -benchmem .
BenchmarkStringFmtAdd-2 2973 404782 ns/op 3231129 B/op 2002 allocs/op
PASS
ok learn-go 2.455s
# go test -bench='BenchmarkStringBuilderAdd' -cpu=2 -count=1 -benchmem .
BenchmarkStringBuilderAdd-2 256581 4671 ns/op 24824 B/op 14 allocs/op
PASS
ok learn-go 2.419s
# go test -bench='BenchmarkStringBytesBufferAdd' -cpu=2 -count=1 -benchmem .
BenchmarkStringBytesBufferAdd-2 206992 5818 ns/op 22464 B/op 9 allocs/op
PASS
ok it******.com/learn-go 2.459s

实测结果(MacBook M1 Pro):

从性能对比上可以看得出来,从内存分配、耗时上,strings.Builder、bytes.Buffer 的性能最优

三、各方案特性解析

方案

说明

+ 运算符拼接

适用场景:简单临时拼接(<10次)<br />隐患:每次操作生成新字符串,O(n^2)时间复杂度<br />内存分配:每次操作触发内存重新分配

fmt 运算拼接

适用场景:需要格式化输出的日志拼接、<br />混合数据类型(int/float/struct)转换<br />临时调试输出等非性能敏感场景

bytes.Buffer

高效构建字节,在处理二进制数据时效率较高,注意 buf 过大时会触发 panic

strings.Builder

高效构建字符串,使用Grow预分配提升性能

结论:

简单拼接场景:+ 运算符拼接、fmt 运算拼接都可以
大量字符串拼接:strings.Builder适用于处理二进制数据,像文件读写、网络数据传输等场景:bytes.Buffer

原文地址:
https://blog.fiveyoboy.com/articles/go-concat-string

相关文章

Python 中 字符串处理的高效方法,不允许你还不知道

以下是 Python 中 字符串处理的高效方法,涵盖常用操作、性能优化技巧和实际应用场景,帮助您写出更简洁、更快速的代码:一、基础高效操作1.字符串拼接:优先用join()代替+原因:join() 预...

打钱专业户!330穿的八级金币黑枪王

大家好,我是你们的游戏小编:冴之木七星在八级,提起黑枪,大家第一个想到的可能还是莱茵(菜田),但是要说最强黑枪车,我Strv S1第一个不服。毕竟:这是一台只为黑枪而生的黑枪车!极高的隐蔽,超高的穿深...

Python字符串比较的隐藏法则:Unicode对决、内存地址暗战!

字符串比较的底层规则核心原理:字符逐个对比,基于Unicode值一决胜负!# 规则演示:从首字符开始逐位比较 print("apple" > "app")...

5岁儿子是不是亲生的?他做了两次鉴定,结果相反

一份亲子鉴定报告,关系着一个甚至多个家庭的幸福。“前几天,有一个宁波慈溪的客户火冒三丈地来投诉,说亲子鉴定结果错了。结果,这是一场闹剧。”宁波天童司法鉴定中心主任许卫平和记者说起了一件事。他说,这事,...

【超测前瞻】涅槃重生,这一世它是全能铲车王!

前言虽拥有大威力大口径主炮,但S系VIII级坦歼“库斯特工程”的表现并不如意,甚至在整个“液压攻城坦歼”家族当中,它的表现都要相对靠后。时光悄然流逝,库斯特工程已是边缘过气坦,它之前另一位早早进入超测...

Java中你知道几种从字符串中找指定的字符的数量

遇到这样的问题,常规的思路估计就是遍历String,然后逐个对比。下面先看循环遍历循环遍历private static int getNum(String originStr, String targ...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。