String concatenation is indispensable in everyday coding, and the most commonly used is the native concatenation method (+=
). However, its performance is fine for a small number of splices, but for a large number of string splices, other more efficient methods should be used.
This article first lists several string concatenation methods commonly used in Golang, and then benchmarks them, so that after reading this article, we can have a basic understanding of the applicability of various concatenation methods.
1 How many ways are there for string concatenation?
We are inevitably asked in Golang usage, “How many ways are there to splice strings?” . Here is a list of them.
a) Native concatenation (+=)
The native concatenation method uses the +
operator to splice two strings directly.
The following code uses +=
to splice and reassign strings.
Why is this approach not efficient? Because string is immutable in Golang, the value of s has to be taken down (copied from the top), then spliced with a string, and then the new value (a brand new string) is assigned to s again after the calculation, while the old value of s will wait for the garbage collector. Since each splice is iteratively copied from the beginning, it involves more computation and memory allocation.
The time complexity of this approach is O(N^2)
.
b) bytes.Buffer
Buffer is a variable-length byte buffer. It uses slice internally to store bytes (buf []byte
).
When using WriteString for string concatenation, it dynamically extends the slice length according to the situation and copies the string to be spliced into the buffer using the built-in slice memory copy function. Since it is a variable-length slice, each time you splice, you do not need to re-copy the old part, but only append the part to be spliced to the end, so it has higher performance than the native concatenation method.
The time complexity of this method is O(N)
.
|
|
c) strings.Builder
The strings.Builder also uses byte slice internally for storage.
When using WriteString for string stitching, the built-in append function is called and only the string to be stitched is merged into the buffer. It is also very efficient.
d) Built-in copy function
The built-in copy function supports copying a source slice to a target slice, and since the underlying representation of a string is []byte
, you can also use this function for string concatenation. However, the limitation is that the length of the byte slice needs to be known in advance.
The built-in copy function supports copying from one slice to another (it supports copying a string to []byte
), and the return value is the length of the copied element.
The return value is the length of the element copied. Each time it splices, it only needs to append the string to be spliced to the end of the slice, which is also very efficient.
|
|
e) strings.Join
If you want to put the parts of a string slice ([]string
) into a single string, you can use strings.Join
to do so.
|
|
Its internal implementation is also done using bytes. So it is also very efficient.
|
|
2 Benchmarking
The string concatenation methods described above are assembled into a test file, string_test.go
, for benchmarking. (Because strings.Join
requires a pre-generated []string
, it is not used in the same scenario as the other methods, so it is not included in this test)
The benchmark test will use each method to splice a string s
1000 times.
string_test.go Source code.
|
|
Execute the Benchmark test command.
|
|
You can see that the built-in copy function with strings.Builder is the most efficient way, bytes.Buffer is the next most inefficient, and the native concatenation way is the most inefficient.