缓冲区的作用是什么,既然我们可以将数据存储在字符串变量中?

huangapple go评论85阅读模式
英文:

What is the purpose of the buffer when we can store in a string variable?

问题

为什么我要使用缓冲区而不是直接连接字符串?

以下是伪代码

var buffer bytes.Buffer 
for i := 0; i < 200; i++ {
    buffer.WriteString(strconv.Itoa(i))
}
fmt.Println(buffer.String())

buffer := ""
for i := 0; i < 200; i++ {
    buffer += strconv.Itoa(i)
}
fmt.Println(buffer)

相比,使用缓冲区的方法更有效率。在循环中,每次连接字符串时,使用缓冲区可以避免创建新的字符串副本。相反,它将字符串片段追加到缓冲区中,最后再一次性生成最终的字符串。这样可以减少内存分配和垃圾回收的开销,提高性能。因此,使用缓冲区可以更好地处理大量字符串连接的情况。

英文:

Why would I want to use a buffer when I can just concatenate strings?

PSEUDO CODE BELOW

var buffer bytes.Buffer 
for i := 0; i &lt; 200; i++ {
    buffer.WriteString(strconv.Itoa(i))
}
fmt.Println(buffer.String())

Vs

buffer := &quot;&quot;
for i := 0; i &lt; 200; i++ {
    buffer += strconv.Itoa(i)
}
fmt.Println(buffer)

答案1

得分: 7

一个缓冲区以块的方式增长,以分摊内存分配的开销。

由于字符串是不可变的,每次循环迭代都必须分配一个新的字符串。

英文:

A buffer grows in chunks to amortize memory allocations.

Because strings are immutable, every iteration through the loop must allocate a new string.

答案2

得分: 3

你可以将缓冲区视为一个队列,你可以将事物按顺序放入其中。每个人都只是一个接一个地排队,非常高效,添加新项目不会占用额外的空间。你只需插入它们,然后完成。

所以当你将A、B、C、D、E添加到缓冲区时,内存操作看起来像这样:

缓冲区=A
缓冲区=A|B
缓冲区=A|B|C
缓冲区=A|B|C|D
缓冲区=A|B|C|D|E

现在,如果你连接字符串,将不得不分配和重新分配大量的内存

 字符串=&#39;&#39;
 字符串=分配(A),分配(字符串+A),释放(字符串=&#39;&#39;)
 字符串=分配(B),分配(字符串(&#39;&#39;|A)+B),释放(字符串=&#39;&#39;|A)
 字符串=分配(C),分配(字符串(&#39;&#39;|A|B)+C),释放(字符串=&#39;&#39;|A|B)
 字符串=分配(D),分配(字符串(&#39;&#39;|A|B|C)+D),释放(字符串=&#39;&#39;|A|B|C)
 字符串=分配(E),分配(字符串(&#39;&#39;|A|B|C|D)+E),释放(字符串=&#39;&#39;|A|B|C|D)

如你所见,通过不断添加到字符串中,必须创建一个新的字符串,由旧字符串和新字符串组成,然后释放旧字符串。
这会导致大量的垃圾内存。当你在缓冲区中添加时,你只需整齐地排列一切,而不会占用太多额外的内存。

而如果你连接字符串,你不断地分配更新和更大的变量。
旧字符串 + 追加字符串 + 新的连接字符串。这样不断增长。
如果你读取一个大文件的每一行,这可能会在一段时间后导致内存不足错误。

英文:

You can see a buffer as a queue where you place things in line. Everyone just shoves in line one behind the other, it's very efficient and doesn't take up extra space to add new items. You just insert them and you are done.

So when you add A, B, C, D,E to a buffer the operation will look kinda like this memory wise:

buffer=A
buffer=A|B
buffer=A|B|C
buffer=A|B|C|D
buffer=A|B|C|D|E

Now, if you concatenate strings, a lot of memory will have to be allocated and reallocated

 str=&#39;&#39;
 str=Allocate(A),allocate(str+A),deallocate(str=&#39;&#39;)
 str=Allocate(B),allocate(str(&#39;&#39;|A)+B),deallocate(str=&#39;&#39;|A)
 str=Allocate(C),allocate(str(&#39;&#39;|A|B)+C),deallocate(str=&#39;&#39;|A|B)
 str=Allocate(D),allocate(str(&#39;&#39;|A|B|C)+D),deallocate(str=&#39;&#39;|A|B|C)
 str=Allocate(E),allocate(str(&#39;&#39;|A|B|C|D)+E),deallocate(str=&#39;&#39;|A|B|C|D)

As you can see, by constantly adding to the string a new string as to be created, composed of the old string, then the new string is made and the old string gets deallocated.
This causes a lot of junk memory. When you add in a buffer you just neatly line up everything without taking up to much extra memory.

Whilst if you concatenate the strings, you are constantly assigning newer and bigger variables.
Oldstring + append string + new concat string. and this grows and grows and grows.
If you have a big file you read line by line this might give some out of memory errors after a while.

答案3

得分: 2

在Go语言中,字符串是不可变的。因此,第二个示例在每次迭代时都会分配一个新的字符串,因此运行时间为O(n^2)。

英文:

Strings are immutable in Go. So the second example will allocate a new string on each iteration, so will have O(n^2) runtime.

huangapple
  • 本文由 发表于 2016年1月9日 03:36:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/34684751.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定