当我们可以存储在字符串变量中时,缓冲区的目的是什么?

当我们可以存储在字符串变量中时,缓冲区的目的是什么?

问题描述:

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 < 200; i++ {
    buffer.WriteString(strconv.Itoa(i))
}
fmt.Println(buffer.String())

Vs

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

A buffer grows in chunks to amortize memory allocations.

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

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

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=''
 str=Allocate(A),allocate(str+A),deallocate(str='')
 str=Allocate(B),allocate(str(''|A)+B),deallocate(str=''|A)
 str=Allocate(C),allocate(str(''|A|B)+C),deallocate(str=''|A|B)
 str=Allocate(D),allocate(str(''|A|B|C)+D),deallocate(str=''|A|B|C)
 str=Allocate(E),allocate(str(''|A|B|C|D)+E),deallocate(str=''|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.