preface

In daily development, one of the most written code is string concatenation, such as log input concatenation, response parameter concatenation, etc. What are the methods for concatenating strings in Golang? And how effective they are, and we’re going to put that to the test.

way

“+” or “+ =”

// Add strings
func stringPlus(s string, count int) (res string) {
	for i := 0; i < count; i++ {
		res += s
	}
	return
}
Copy the code

FMT built-in library

//fmt.Sprintf
func stringFmtSprintf(s string, count int) (res string) {
	for i := 0; i < count; i++ {
		res = fmt.Sprintf("%s%s", res, s)
	}
	return
}
Copy the code

bytes.Buffer

//bytes.Buffer
func stringBytesBuffer(s string, count int) (res string) {
	buf := &bytes.Buffer{}
	for i := 0; i < count; i++ {
		buf.WriteString(s)
	}
	res = buf.String()
	return
}
Copy the code

strings.Builder

//strings.Builder
func stringStringsBuilder(s string, count int) (res string) {
	build := &strings.Builder{}
	for i := 0; i < count; i++ {
		build.WriteString(s)
	}
	res = build.String()
	return
}
Copy the code

[]byte

/ / byte slice
func stringByteSlice(s string, count int) (res string) {
	b := make([]byte.len(s))
	for i := 0; i < count; i++ {
		b = append(b, s...)
	}
	res = string(b)
	return
}
Copy the code

performance

Here are five common string concatenation methods in Golang. What is their concatenation performance? Let’s test this with benchmarks:

package main

import "testing"

const (
	testString = "a"
	testCount = 1000
)

func BenchmarkStringPlus(b *testing.B) {
	for i := 0; i < b.N; i++ {
		stringPlus(testString, testCount)
	}
}

func BenchmarkStringFmtSprintf(b *testing.B) {
	for i := 0; i < b.N; i++ {
		stringFmtSprintf(testString, testCount)
	}
}

func BenchmarkStringBytesBuffer(b *testing.B) {
	for i := 0; i < b.N; i++ {
		stringBytesBuffer(testString, testCount)
	}
}

func BenchmarkStringStringsBuilder(b *testing.B) {
	for i := 0; i < b.N; i++ {
		stringStringsBuilder(testString, testCount)
	}
}

func BenchmarkStringByteSlice(b *testing.B) {
	for i := 0; i < b.N; i++ {
		stringByteSlice(testString, testCount)
	}
}
Copy the code

The result is:

goos: windows goarch: amd64 pkg: go-juejin/strappend cpu: Intel(R) Core(TM) i5-9400F CPU @ 2.90ghz BenchmarkStringPlus BenchmarkStringPlus-6 9313 129762 ns/op BenchmarkStringFmtSprintf BenchmarkStringFmtSprintf-6 4152 260648 ns/op BenchmarkStringBytesBuffer BenchmarkStringBytesBuffer-6 181897 6579 ns/op BenchmarkStringStringsBuilder BenchmarkStringStringsBuilder-6 280454 4355  ns/op BenchmarkStringByteSlice BenchmarkStringByteSlice-6 925546 1212 ns/op PASSCopy the code

It can be seen that in the case of a large amount of data, the []byte mode is the best, while the FMT.Sprintf mode has the worst performance. If you know the string length, the []byte mode is preferred.

Afterword.

In different situations to choose different stitching methods, in order to make our efficiency twice the result with half the effort.

Finally, thank you for reading, thank you!