Created
October 31, 2021 11:02
-
-
Save gosamplesdev/3a319617bd3afb8b9b47edc3fcf29d5d to your computer and use it in GitHub Desktop.
A benchmark comparing different string concatenation methods in Go (Golang). See more on https://gosamples.dev/concatenate-strings/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package benchmark | |
import ( | |
"bytes" | |
"fmt" | |
"strings" | |
"testing" | |
) | |
const ( | |
hello = "hello" | |
gosamples = "https://gosamples.dev" | |
) | |
func generateStrings(withSeparator bool) (data []string, size int) { | |
for i := 0; i < 100; i++ { | |
data = append(data, hello) | |
size += len(hello) | |
if withSeparator { | |
data = append(data, " ") | |
size++ | |
} | |
data = append(data, gosamples) | |
size += len(gosamples) | |
if withSeparator { | |
data = append(data, " ") | |
size++ | |
} | |
} | |
if withSeparator { | |
data = data[:len(data)-1] | |
size-- | |
} | |
return data, size | |
} | |
func BenchmarkPlusOperatorUnknownSize(b *testing.B) { | |
data, _ := generateStrings(true) | |
var s string | |
for n := 0; n < b.N; n++ { | |
for _, d := range data { | |
s += d | |
} | |
_ = s | |
} | |
} | |
func BenchmarkSprintfKnownSize(b *testing.B) { | |
data, _ := generateStrings(false) | |
var interfaceData []interface{} | |
for _, d := range data { | |
interfaceData = append(interfaceData, d) | |
} | |
format := strings.Repeat("%s ", len(interfaceData)) | |
format = strings.TrimSuffix(format, " ") | |
var s string | |
for n := 0; n < b.N; n++ { | |
s = fmt.Sprintf(format, interfaceData...) | |
_ = s | |
} | |
} | |
func BenchmarkStringBuilderUnknownSize(b *testing.B) { | |
data, _ := generateStrings(true) | |
var s string | |
for n := 0; n < b.N; n++ { | |
var builder strings.Builder | |
for _, s := range data { | |
builder.WriteString(s) | |
} | |
s = builder.String() | |
_ = s | |
} | |
} | |
func BenchmarkStringBuilderKnownSize(b *testing.B) { | |
data, size := generateStrings(true) | |
var s string | |
for n := 0; n < b.N; n++ { | |
var builder strings.Builder | |
builder.Grow(size) | |
for _, s := range data { | |
builder.WriteString(s) | |
} | |
s = builder.String() | |
_ = s | |
} | |
} | |
func BenchmarkJoinKnownSize(b *testing.B) { | |
data, _ := generateStrings(false) | |
var s string | |
for n := 0; n < b.N; n++ { | |
s = strings.Join(data, " ") | |
_ = s | |
} | |
} | |
func BenchmarkBytesBufferUnknownSize(b *testing.B) { | |
data, _ := generateStrings(true) | |
var s string | |
for n := 0; n < b.N; n++ { | |
var buffer bytes.Buffer | |
for _, s := range data { | |
buffer.WriteString(s) | |
} | |
s = buffer.String() | |
_ = s | |
} | |
} | |
func BenchmarkBytesBufferKnownSize(b *testing.B) { | |
data, size := generateStrings(true) | |
var s string | |
for n := 0; n < b.N; n++ { | |
var buffer bytes.Buffer | |
buffer.Grow(size) | |
for _, s := range data { | |
buffer.WriteString(s) | |
} | |
s = buffer.String() | |
_ = s | |
} | |
} | |
func BenchmarkByteSliceUnknownSize(b *testing.B) { | |
data, _ := generateStrings(true) | |
var s string | |
for n := 0; n < b.N; n++ { | |
var byteSlice []byte | |
for _, s := range data { | |
byteSlice = append(byteSlice, []byte(s)...) | |
} | |
s = string(byteSlice) | |
_ = s | |
} | |
} | |
func BenchmarkByteSliceKnownSize(b *testing.B) { | |
data, size := generateStrings(true) | |
var s string | |
for n := 0; n < b.N; n++ { | |
byteSlice := make([]byte, 0, size) | |
for _, s := range data { | |
byteSlice = append(byteSlice, []byte(s)...) | |
} | |
s = string(byteSlice) | |
_ = s | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment