阅读Does Go language use Copy-on-write for strings的答案后 ,我觉得这个问题没有得到足够的回答。
以下面的示例为例,引擎盖下到底发生了什么?
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\n", s, t)
}
输出:
HelloWorld HelloThere
问题是golang何时会确定需要创建新副本?
答案 0 :(得分:3)
在Go中,字符串值是read-only
字节片,并且您不能更改其元素(不可变)。由于它是切片,因此意味着它具有定义了容量的支持(底层)阵列。话虽这么说,我们可以说字符串是一个指向只读后备数组的数据结构。
为高可重用性而对字符串进行了优化,因此是只读的。每当您修改字符串时,都会在后台创建一个新的字符串(字节片),这会使它的操作成本很高。一种建议是将字符串转换为实际的字节片[]byte(string)
并处理字节,或者在程序需要进行大量字符串操作时使用strings.Builder。
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
答案 1 :(得分:-1)
在评论部分对进行了大量辩论/讨论之后,这是我的结论。
Golang没有写时复制。
这里的 + = 是一个显式创建的新字符串,它等效于 s = s +“ World” ,该字符串将创建一个新字符串并将其分配回< strong> s
如果您尝试编写以下代码,由于golang字符串的不变性,将导致编译错误
t[0] = 'A' // cannot assign to t[0]
因此,golang中的所有内容都是显式的,golang在后台没有任何隐式处理。这就是为什么Golang中不存在写时复制的原因。
注意:COW和不变性不是互斥的。