Understanding Data Structure of Type Slice.¶
Objective¶
Understanding Slice's in Go.
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 |
|
For our program create a new folder '12_slice'
1 |
|
And lets create a file 'slice.go' in it, finally the structure would look like this:
1 |
|
Declaration¶
Syntax
Declaration & initialization method
1 |
|
With built-in function make()
1 |
|
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 |
|
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 |
|
Above line declares a slice and initializes its value, in this case length & capacity are equal.
1 |
|
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 |
|
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 |
|
Now we can insert values upto length = 10 or index = 9. On line 54 we print out our new slice.
1 |
|
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 |
|
Then we print out the slice on line 59.
1 |
|
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 |
|
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 |
|
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 |
|
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 |
|
Once in the folder type the following command
1 |
|
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 |
|
If for some reason your code isn't working, checkout the github repo or playground.
Github¶
Golang Playground¶
Next¶
In the next chapter we will study Maps.