The capacity growth is not under user control:
append(s S, x ...T) S // T is the element type of S
If the capacity of s is not large enough to fit the additional values,
append allocates a new, sufficiently large underlying array that fits
both the existing slice elements and the additional values. Otherwise,
append re-uses the underlying array.
ref: https://golang.org/ref/spec#Appending_and_copying_slices
and see: https://golang.org/doc/effective_go.html#append
it is not increased by 2 (it is performance optimized):
test sample code with initial capacity 5 bytes then it is 16 instead of 10 (see commented output):
package main
import "fmt"
func main() {
s := []byte{1, 2, 3, 4, 5}
fmt.Println(cap(s)) // 5
s = append(s, s...)
fmt.Println(cap(s)) // 16
}
test sample code (with commented output):
package main
import (
"fmt"
)
func main() {
s := []int{0}
fmt.Println(cap(s)) // 1
s = append(s, s...)
fmt.Println(cap(s)) // 2
}
test sample code (with commented output):
package main
import (
"fmt"
)
func main() {
s := []int{}
fmt.Println(cap(s)) // 0
s = append(s, 1)
fmt.Println(cap(s)) // 1
}
test sample code with nil slice (with commented output):
package main
import (
"fmt"
)
func main() {
var s []int
fmt.Println(cap(s)) // 0
s = append(s, 1)
fmt.Println(cap(s)) // 1
}
your sample code (with commented output):
package main
import "fmt"
func main() {
var s1 []int
s2 := append(s1, 1)
fmt.Println(cap(s1)) // 0
fmt.Println(cap(s2)) // 1
}
test sample code with 5 ints (with commented output):
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5}
fmt.Println(cap(s)) // 5
s = append(s, s...)
fmt.Println(cap(s)) // 10
}
you can not access uninitialized indexes of slice like s2[1]
:
panic: runtime error: slice bounds out of range:
test sample code (with commented output):
package main
import "fmt"
func main() {
var s1 []int
s2 := append(s1, 1)
fmt.Println(cap(s1)) // 0
fmt.Println(cap(s2)) // 1
fmt.Println(s1) // []
fmt.Println(s2) // [1]
//fmt.Println(s2[0:2]) //panic: runtime error: slice bounds out of range
//fmt.Println(s2[1]) //panic: runtime error: slice bounds out of range
}
Bounds Checking Elimination (or BCE) is a general term for removing
redundant bound checking. Normally a go program will panic when a
slice or a string is accessed outside of its bounds. There are two
types of bound checking: for indexing (a[i]) and for slicing (a[i:j]).
The go compiler inserts these bounds checks at every access, but in
most cases they are not needed and are redundant based on the context.
Bound checking is important because it provides a defense against
buffer overflow attacks and catches a common programming error early.
BCE is important because: it speeds up the code, makes the binary
smaller. If binaries are slowed down by bound checks then developers
will have an incentive to disable bound checking (using -gcflags=-B).
ref