ibigpapa
ibigpapa

Reputation: 41

Why does slicing decrease capacity by one

So I was testing slices and thought that go won't decrease the capacity. But from what i see it does. Does anyone know the reason for the drop in capacity of 1? (go version go1.8 linux/amd64)

package main

import "fmt"

func main() {
    name := make([]int, 0, 100000000)
    fmt.Printf("%d | %d\n", cap(name), len(name))
    for x:= 0; x < 1000; x++ {
        name = append(name, x)
    }
    fmt.Printf("%d | %d\n", cap(name), len(name))
    name2 := name[1:500]
    fmt.Printf("%d | %d\n", cap(name2), len(name2))
}

The output is

100000000 | 0
100000000 | 1000
99999999 | 499

Changing the size to 1000 changes the output to this

1000 | 0
1000 | 1000
999 | 499

Upvotes: 1

Views: 285

Answers (2)

Adrian
Adrian

Reputation: 46442

When you shrink a slice from the left (increasing the slice's start index in the underlying array), you reduce its capacity, because it can never grow to the left. When you shrink a slice from the right (reducing the slice's length), the capacity is unchanged, because a slice can grow to the right. For example:

name := make([]int, 100)
fmt.Printf("%d | %d\n", cap(name), len(name))
name2 := name[:50]  // Won't shrink because left side is unchanged
fmt.Printf("%d | %d\n", cap(name2), len(name2))
name2 = name[50:]   // WILL shrink because left side is moved up
fmt.Printf("%d | %d\n", cap(name2), len(name2))

Outputs:

cap 100 | len 100
cap 100 | len 50
cap 50 | len 50

Playground demo: https://play.golang.org/p/jbGRmexV5d-

Upvotes: 3

miltonb
miltonb

Reputation: 7355

By changing your code to the following (starting at index 0), then the capacity is unchanged inline with what you expected. By using index 1 in the slice you have lost the first item (item at 0) which is why there is an apparent capacity change.

  name2 := name[0:500]
  fmt.Printf("%d | %d\n", cap(name2), len(name2))

Producing the output:

100000000 | 500

Upvotes: 4

Related Questions