SoFunction
Updated on 2025-03-05

Detailed explanation of the difference between length and capacity of slices in Go language

Slice statement

A slice can be regarded as a reference to an array (in fact, the underlying data structure of the slice is indeed an array). existGoIn  , the size of each array is fixed and cannot be changed at will. Slicing can provide dynamic growth and shrinkage requirements for the array, but it does not store any data itself.

// Declaration of arrayvar a [5]int //Only specify the length, the element is initialized to the default value 0var a [5]int{1,2,3,4,5}

// Slice statement// Method 1: Direct initializationvar s []int //Declare a nil slice with length and capacity of 0var s []int{1,2,3,4,5} // Create an array of length 5 at the same time// Method 2: Use make() function to create slicesvar s = make([]int, 0, 5)

// Slice array: var variable name []Variable type = arr[low, high], low and high are the indexes of the array.// Remember the rules are: close left and open rightvar arr = [5]int{1,2,3,4,5}
var slice []int = arr[1:4] // [2,3,4]

Length and capacity of slices

The length of the slice is the number of elements it contains. The capacity of a slice is the number from its first element to the end of its underlying array element. SlicesThe length and capacity of   can be expressed through expressionlen(s)andcap(s)Come and get it.

s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
(s, len(s), cap(s))
// output: [0 1 2 3 4 5 6 7 8 9] 10 10

s1 := s[0:5]
(s1, len(s1), cap(s1))
// output: [0 1 2 3 4] 5 10

s2 := s[5:]
(s2, len(s2), cap(s2))
// output: [5 6 7 8 9] 5 5

Changes in length and capacity after adding elements in slices

append function

GoProvides built-inappendFunction, append new elements to the slice.

func append(s []T, vs ...T) []T

appendThe return value of  is a slice containing all elements of the original slice plus the newly added element.

s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
(s, len(s), cap(s))
sResult := append(s, 11)
(sResult, len(sResult), cap(sResult))
// output: 
// [0 1 2 3 4 5 6 7 8 9] 10 10
// [0 1 2 3 4 5 6 7 8 9 11] 11 20

At this time, we can discover that when weappendWhen elements enter the slice, the length and capacity of the original slice change, but why does their changes happen?

Let’s take a look at how the source code is implemented.

Learning the source code of slices

GoThe data structure of the slice can be in the source codesrc/runtime/View in  . The following source code is based ongo1.16.7Version.

Sliced ​​structure

As a reference to an array, slices have three attribute fields: pointer to the array, length and capacity.

type slice struct {
  // Pointer to the underlying array	array 
  // slice The current number of elements, that is, the number returned by len()	len   int
  // The capacity of slice, that is, the number returned when cap()	cap   int
}

Slice expansion

sliceBy callingappendFunctions are targetedsliceAppend elements at the tail, if at this timesliceofcapValue is less than the currentlenPlusappendThe number of values ​​passed in will be calledFunction, expand capacity.

We only release code analysis of basic expansion rules here. If you are interested in memory alignment, data copying, etc., you can view the corresponding source code yourself.

Basic expansion rules

func growslice(et *_type, old slice, cap int) slice {
    newcap := 
    doublecap := newcap + newcap
    // If the new capacity is greater than twice the old capacity, apply directly according to the new capacity size    if cap > doublecap {
			newcap = cap
    } else {
        // If the original length is less than 1024, the new capacity is twice the old capacity        if  < 1024 {
            newcap = doublecap
        } else {
            // Increase at 1/4 of the original capacity until the new capacity needs are met            for 0 < newcap && newcap < cap {
                newcap += newcap / 4
            }
            if newcap <= 0 {
                newcap = cap
            }
        }
    }
}

From the source code, you can actually sort out several rules:

When the original slice length is less than 1024, the new slice length is directly addedappendThe number of elements and capacity will be directly*2

When the original slice length is greater than or equal to 1024, the new slice length is directly addedappendThe number of elements will increase1/4

Summarize

A slice is a structure that holds the capacity, length and pointers to an array (the address of the array).

From the source code, when a slice is expanded, it will growslice, which is a very expensive operation. In daily development, if we can clearly know the length or capacity of the slice, we need to declare it during initialization to avoid the expenses caused by frequent expansion of the slice.

This is the end of this article about explaining the difference between the length and capacity of slices in Go. For more related Go languages, please search for my previous articles or continue browsing the related articles below. I hope you can support me more in the future!