Skip to content

Understanding Data Structure of Type Slice.


Objective

Understanding Slice's in Go.

Slice

Slice are dynamic versions of array, slices can grow & shrink in length as required. Underlying the slice is an array and a pointer to it, exactly how the Go compiler stores the slice is a little complex, we will cover it in the "Intermediate" section of the tutorial.

Structure

Navigate to our code folder

1
code/basic/

For our program create a new folder '12_slice'

1
code/basic/12_slice/

And lets create a file 'slice.go' in it, finally the structure would look like this:

1
code/basic/12_slice/slice.go

Declaration

Syntax

Declaration & initialization method

1
sliceName := []type{value1, value2, ...}

With built-in function make()

1
slice := make([]type, length, capacity)

Make initializes the underlying array with zero value and returns a slice that refers to that array. Make is used extensively to initialize slices.

Code

We will write the code in 4 parts:

1.)

part-1 slice.go
1 package main
2
3 import "fmt"
4
5 func main() {
6    // declaring a nil slice
7    var slice1 []int
8    fmt.Println("slice1:", slice1)
9    fmt.Println("The length of slice1 is:", len(slice1))
10    fmt.Println("The capacity of slice1 is:", cap(slice1))
11    fmt.Println()
12    // declaring a slice with initialization
13    slice2 := []int{1, 2, 3, 4, 5}
14    fmt.Println("slice2:", slice2)
15    fmt.Println("The length of slice2 is:", len(slice2))
16    fmt.Println("The capacity of slice2 is:", cap(slice2))
17    fmt.Println()
18
19    // declaring a slice of length 5 with make
20    slice3 := make([]string, 5)
21    fmt.Println("slice3:", slice3)
22    fmt.Println("The length of slice3 is:", len(slice3))
23    fmt.Println("The capacity of slice3 is:", cap(slice3))
24    fmt.Println()
25

Review

On line 7, 13 & 20 we declare slice using different syntax

1
var slice1 []int

This declares a nil slice, the length & capacity are zero. As you will see in forth coming examples, slices can have variable length and capacity.

Slices can dynamically resize till it reaches its capacity, we will shortly see how this is done.

1
slice2 := []int{1, 2, 3, 4, 5}

Above line declares a slice and initializes its value, in this case length & capacity are equal.

1
slice3 := make([]string, 5)

This initializes a zero value slice with the length & capacity of 5. Note the difference in length & capacity of slice3 as compared to slice1.

2.)

part-2 slice.go
26 // declaring a slice of length 5 and capacity 10 with make
27 slice4 := make([]int, 5, 10)
28 fmt.Println("slice4:", slice4)
29 fmt.Println("The length of slice4 is:", len(slice4))
30 fmt.Println("The capacity of slice4 is:", cap(slice4))
31 fmt.Println()
32
33 // inserting values, note i < 6 will give an error as we have
34 // set the length to 5
35 for i := 0; i < 5; i++ {
36  slice4[i] = i
37 }
38 fmt.Println("slice4:", slice4)
39 fmt.Println()
40
41 // increasing the length of slice
42 fmt.Println("Increasing the length of slice...")
43
44 // slice4 = slice4[:11] will give an error as capacity is 10
45 slice4 = slice4[:10]
46 fmt.Println("The length of slice4 is:", len(slice4))
47 fmt.Println("The capacity of slice4 is:", cap(slice4))
48 for i := 5; i < 10; i++ {
49  slice4[i] = i
50 }
51 fmt.Println()
52
53 // printing slice4
54 fmt.Println("slice4:", slice4)
55 fmt.Println()
56

Review

On line 27 we declare a new slice with length = 5 and capacity = 10.

1
slice4 := make([]int, 5, 10)

Then on line 35 we insert values into the slice, note we insert values only till index = 4 or length = 5 (remember our index starts from 0 and not 1!)

If we exceed length of 5, it will throw an error as we have declared our length as 5.

On line 45 we dynamically increase the length to 10.

1
slice4 = slice4[:10]

Now we can insert values upto length = 10 or index = 9. On line 54 we print out our new slice.

1
fmt.Println("slice4:", slice4)

3.)

part-3 slice.go
57 // creating a new slice
58 slice5 := slice4[2:8]
59 fmt.Println("slice5:", slice5)
60 fmt.Println()
61

Review

We can create new slice from an existing one, on line 58 we create a new slice5 which has values from slice4 but only from index 2 to 8.

1
slice5 := slice4[2:8]

Then we print out the slice on line 59.

1
fmt.Println("slice5:", slice5)

4.)

part-4 slice.go
62 // two-D slice
63 twoD := [][]int{{3, 4}, {1, 5}, {9, 2}, {7, 8}}
64 fmt.Println("Print out values of twoD slice...")
65 for i, subSlice := range twoD {
66  fmt.Printf("At index: %d of twoD, Value: %v\n", i, subSlice)
67  for index, value := range subSlice {
68      fmt.Printf("Index: %d Value: %d\n", index, value)
69  }
70  fmt.Println()
71 }
72 }

Review

Slice can have slices inside it, above we create a two-D slice, i.e a slice inside a slice, you can create multiple dimension slices, e.g three-D or four-D or even larger.

On line 63 we declare a two-D slice of type int

1
twoD := [][]int{{3, 4}, {1, 5}, {9, 2}, {7, 8}}

Note the syntax, it contains a slice within a slice, all separated by curly brackets and comma. On line 65 we start a for-range loop to print all the values inside two-D

1
for i, slice := range twoD

This takes the first slice inside twoD and assigns it to the variable "subSlice", then we again loop over subSlice to print all the values.

1
for index, value := range subSlice

Creating multi-dimension slices also increases the complexity, Go offers multiply other data types to tackle this as we will study then in forth coming chapters.

Full Code

slice.go
package main

import "fmt"

func main() {
    // declaring a nil slice
    var slice1 []int
    fmt.Println("slice1:", slice1)
    fmt.Println("The length of slice1 is:", len(slice1))
    fmt.Println("The capacity of slice1 is:", cap(slice1))
    fmt.Println()
    // declaring a slice with initialization
    slice2 := []int{1, 2, 3, 4, 5}
    fmt.Println("slice2:", slice2)
    fmt.Println("The length of slice2 is:", len(slice2))
    fmt.Println("The capacity of slice2 is:", cap(slice2))
    fmt.Println()

    // declaring a slice of length 5 with make
    slice3 := make([]string, 5)
    fmt.Println("slice3:", slice3)
    fmt.Println("The length of slice3 is:", len(slice3))
    fmt.Println("The capacity of slice3 is:", cap(slice3))
    fmt.Println()

    // declaring a slice of length 5 and capacity 10 with make
    slice4 := make([]int, 5, 10)
    fmt.Println("slice4:", slice4)
    fmt.Println("The length of slice4 is:", len(slice4))
    fmt.Println("The capacity of slice4 is:", cap(slice4))
    fmt.Println()

    // inserting values, note i < 6 will give an error as we have
    // set the length to 5
    for i := 0; i < 5; i++ {
        slice4[i] = i
    }
    fmt.Println("slice4:", slice4)
    fmt.Println()

    // increasing the length of slice
    fmt.Println("Increasing the length of slice...")

    // slice4 = slice4[:11] will give an error as capacity is 10
    slice4 = slice4[:10]
    fmt.Println("The length of slice4 is:", len(slice4))
    fmt.Println("The capacity of slice4 is:", cap(slice4))
    for i := 5; i < 10; i++ {
        slice4[i] = i
    }
    fmt.Println()

    // printing slice4
    fmt.Println("slice4:", slice4)
    fmt.Println()

    // creating a new slice
    slice5 := slice4[2:8]
    fmt.Println("slice5:", slice5)
    fmt.Println()

    // two-D slice
    twoD := [][]int{{3, 4}, {1, 5}, {9, 2}, {7, 8}}
    fmt.Println("Print out values of twoD slice...")
    for i, slice := range twoD {
        fmt.Printf("At index: %d of twoD, Value: %v\n", i, slice)
        for index, value := range slice {
            fmt.Printf("Index: %d Value: %d\n", index, value)
        }
        fmt.Println()
    }
}

Running your code

Open your terminal and navigate to our folder

1
code/basic/12_slice/

Once in the folder type the following command

1
go run slice.go

Output

If there are no errors, you should get the output as:

Output
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
slice1: []
The length of slice1 is: 0
The capacity of slice1 is: 0

slice2: [1 2 3 4 5]
The length of slice2 is: 5
The capacity of slice2 is: 5

slice3: [    ]
The length of slice3 is: 5
The capacity of slice3 is: 5

slice4: [0 0 0 0 0]
The length of slice4 is: 5
The capacity of slice4 is: 10

slice4: [0 1 2 3 4]

Increasing the length of slice...
The length of slice4 is: 10
The capacity of slice4 is: 10

slice4: [0 1 2 3 4 5 6 7 8 9]

slice5: [2 3 4 5 6 7]

Print out values of twoD slice...
At index: 0 of twoD, Value: [3 4]
Index: 0 Value: 3
Index: 1 Value: 4

At index: 1 of twoD, Value: [1 5]
Index: 0 Value: 1
Index: 1 Value: 5

At index: 2 of twoD, Value: [9 2]
Index: 0 Value: 9
Index: 1 Value: 2

At index: 3 of twoD, Value: [7 8]
Index: 0 Value: 7
Index: 1 Value: 8

If for some reason your code isn't working, checkout the github repo or playground.

Github

Github Repo

Golang Playground

Golang Playground

Next

In the next chapter we will study Maps.

Buy Me A Coffee

Buy Me A Coffee