Reputation: 893
In the Go Programming Language book, the author gave the following code example of an append()
function that accepts as arguments a []int
and an int
, and will handle resize accordingly:
// gopl.io/ch4/append
func appendInt(x []int, y int) []int {
var z []int
zlen := len(x) + 1
if zlen <= cap(x) {
// There is room to grow. Extend the slice.
z = x[:zlen]
} else {
// There is insufficient space. Allocate a new array.
// Grow by doubling, for amortized linear complexity.
zcap := zlen
if zcap < 2*len(x) { // Question: Why not len(x) > 1?
zcap = 2 * len(x)
}
z = make([]int, zlen, zcap)
copy(z, x)
}
z[len(x)] = y
return z
}
Why is the innermost check written as if zcap < 2*len(x)
instead of the equivalent if len(x) > 1
?
The latter appears clearer to me and signals the intention that if the initial slice has length of 0 or 1, we do not allocate additional capacity after appending the new element.
zcap < 2*len(x)
and len(x) > 1
We can see that the value of zcap
is assigned from zlen
, which in turn has the value len(x) + 1
, so if we arrange the inequality:
zcap < 2*len(x)
after substituting zcap := zlen
, we get:
zlen < 2*len(x)
after substituting zlen := len(x) + 1
, we get:
len(x) + 1 < 2*len(x)
after rearranging, we get:
len(x) > 1
Upvotes: 0
Views: 65
Reputation: 492
You are right, zcap < 2*len(x)
is equivalent to len(x) > 1
. You could totally replace zcap < 2*len(x)
with len(x) > 1
in this function.
But according to the source code, There is another function named appendslice
. In this function, you couldn't do a replacement.
I think author use zcap < 2*len(x)
only for keeping two function consistent. The main purpose here is to avoid frequent allocation.
Upvotes: 1