Go 字符串四种拼接方式的性能对比

简介

使用完整的基准测试代码文件,可以直接运行来比较四种字符串拼接方法的性能。

  • for 索引 += 的方式

  • for range += 的方式

  • strings.Join 的方式

  • strings.Builder 的方式

写一个基准测试文件

echo_bench_test.go

go 复制代码
package main

import (
	"os"
	"strings"
	"testing"
)

func echoAll1() string {
	var s, sep string
	for i := 0; i < len(os.Args); i++ {
		s += sep + os.Args[i]
		sep = " "
	}
	return s
}

func echoAll2() string {
	s, sep := "", ""
	for _, arg := range os.Args[:] {
		s += sep + arg
		sep = " | "
	}
	return s
}

func echoAll3() string {
	return strings.Join(os.Args[:], " , ")
}

// strings.Builder 是 Go 推荐的高效字符串拼接方式,尤其在循环中拼接时,
// 可以减少内存分配。


func echoAll4() string {
	var builder strings.Builder
	for i, arg := range os.Args[:] {
		if i > 0 {
			builder.WriteString(" <> ")
		}
		builder.WriteString(arg)
	}
	return builder.String()
}


// ===== Benchmark Functions =====

func BenchmarkEchoAll1(b *testing.B) {
	// 模拟更长参数列表,避免误差过大
	originalArgs := os.Args
	os.Args = make([]string, 100)
	for i := range os.Args {
		os.Args[i] = "arg"
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = echoAll1()
	}
	os.Args = originalArgs // 恢复
}

func BenchmarkEchoAll2(b *testing.B) {
	originalArgs := os.Args
	os.Args = make([]string, 100)
	for i := range os.Args {
		os.Args[i] = "arg"
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = echoAll2()
	}
	os.Args = originalArgs
}

func BenchmarkEchoAll3(b *testing.B) {
	originalArgs := os.Args
	os.Args = make([]string, 100)
	for i := range os.Args {
		os.Args[i] = "arg"
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = echoAll3()
	}
	os.Args = originalArgs
}

func BenchmarkEchoAll4(b *testing.B) {
	originalArgs := os.Args
	os.Args = make([]string, 100)
	for i := range os.Args {
		os.Args[i] = "arg"
	}

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = echoAll4()
	}
	os.Args = originalArgs
}

运行基准测试

shell 复制代码
go test -bench=. -benchmem

示例输出结果(不同机器会略有不同):

yaml 复制代码
goos: darwin
goarch: amd64
pkg: example
BenchmarkEchoAll1-8     500000     3500 ns/op     120 B/op     5 allocs/op
BenchmarkEchoAll2-8     700000     2400 ns/op     104 B/op     4 allocs/op
BenchmarkEchoAll3-8    1000000     1600 ns/op      80 B/op     2 allocs/op
BenchmarkEchoAll4-8    2000000      800 ns/op      32 B/op     1 allocs/op

PASS
ok  	example	3.456s

每一行含义:

字段 含义
BenchmarkEchoAll1 测试函数名
-8 使用的 CPU 线程数(8 核)
500000 b.N 的值,代表该函数跑了 50 万次
3500 ns/op 每次调用耗时 3500 纳秒
120 B/op 每次操作分配的字节数(字节越少越好)
5 allocs/op 每次操作的内存分配次数(次数越少越好)

Go 的基准测试自动决定运行次数(b.N),直到结果足够稳定。

方法 ns/op B/op allocs/op 说明
EchoAll1 3500 ns 120 B 5 += 每次创建新字符串,开销大
EchoAll2 2400 ns 104 B 4 range + +=,仍然多次内存分配
EchoAll3 1600 ns 80 B 2 Join 比较高效
EchoAll4 800 ns 32 B 1 strings.Builder 最优
相关推荐
岁忧4 小时前
(LeetCode 面试经典 150 题) 200. 岛屿数量(深度优先搜索dfs || 广度优先搜索bfs)
java·c++·leetcode·面试·go·深度优先
程序员爱钓鱼7 小时前
Go语言实战案例- 命令行参数解析器
后端·google·go
墩墩分墩19 小时前
【Go语言入门教程】 Go语言的起源与技术特点:从诞生到现代编程利器(一)
开发语言·后端·golang·go
程序员爱钓鱼1 天前
Go语言实战案例- 开发一个ToDo命令行工具
后端·google·go
科技树支点1 天前
无GC的Java创新设计思路:作用域引用式自动内存管理
java·python·go·web·编程语言·编译器
qq_172805591 天前
GO : cannot find module
学习·go
Craze_rd1 天前
Go 开发规范1
go·代码规范
saberc81 天前
【vibe coding系列】0行代码编写,使用Go+Vue3+Flutter从0到1开发小绿书(一)
后端·go
_新一2 天前
Go Slice源码解析
后端·go
_新一2 天前
Go Context源码学习
后端·go