Golang是否会在修改/写入时复制字符串?

时间:2019-08-12 08:35:12

标签: go

阅读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何时会确定需要创建新副本?

2 个答案:

答案 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

StringHeader - data structure

String Data Type in GO

答案 1 :(得分:-1)

在评论部分对进行了大量辩论/讨论之后,这是我的结论。

Golang没有写时复制。

这里的 + = 是一个显式创建的新字符串,它等效于 s = s +“ World” ,该字符串将创建一个新字符串并将其分配回< strong> s

如果您尝试编写以下代码,由于golang字符串的不变性,将导致编译错误

t[0] = 'A' // cannot assign to t[0]

因此,golang中的所有内容都是显式的,golang在后台没有任何隐式处理。这就是为什么Golang中不存在写时复制的原因。

注意:COW和不变性不是互斥的。