After reading the answer on Does Go language use Copy-on-write for strings , I feel the question was not adequately answered.
Given the example below, what is actually happening under the hood?
package main
import "fmt"
func main() {
s := "Hello"
t := s // t shares the same data as s
s += "World" // a new string is created
t += "There" // a new string is created.
fmt.Printf("%s %s
", s, t)
}
output:
HelloWorld HelloThere
The question is when will golang determine there is a need to create a new copy?
In Go, string values are read-only
byte slices and you cannot change its elements (immutable). Since it is a slice, it means that it has a backing (underlaying) array that has defined capacity. This being said, we can say that string is a data structure that points to a read-only backing array.
Strings are optimized for high reusability and thus read-only. Whenever you modify a string a new string (byte slice) is created in the background which makes it a bit of costly operation. One recommendation is to convert a string to an actual byte slice []byte(string)
and work with bytes or use strings.Builder when your program needs to do a lot of string manipulations.
s := "Hello" // backing array for "hello" created; `s` points to the backing array
t := s // `t` a new string structure and points to the same backing array as `s`,
s += "World" // new backing array created for "HelloWorld"; `s` points to the new backing array
t += "There" // `t` was still pointing to "Hello" and with this operation, a new backing array is created for "HelloThere" and `t` points to it
After much debate/discussion on the at the comment sections, here is my conclusion.
Golang does not have copy-on-write.
The += here is an explicitly creating a new string which is equivalent to s = s + "World" which creates a new string and assign it back to s
And if you try to write the following code, it will result in compilation error due to immutability of the golang string
t[0] = 'A' // cannot assign to t[0]
As a result, everything in golang is explicit, nothing is done implicitly by golang in the background. That is why copy-on-write does not exist in Golang.
Note: COW and immutability are not mutually exclusive.