Slices in Golang

Slices are resizable arrays that provide huge flexibility when working with it. In this post, we will see how to use slices in Golang.

Declaration of a slice

A slice is declared just like an array but without mentioning its size.

package main

func main() {
	var aslice []string     // a string slice
}

Difference between slices and arrays

Arrays, after declared of some size, cannot be resized, whereas slices can be resized. Slices are reference-types while arrays are value-type.

Creating slices in Golang

Noe, we will see how we can create slices for our usage. There are quite a few ways we can create a slice.

1. Using slice literal syntax

Slice literal is the initialization syntax of a slice. Below is an example of using slice literal syntax to create a slice.

package main

import "fmt"

func main() {
	var stringSlice = []string{"This", "is", "a", "string", "slice"}
	fmt.Println(stringSlice)  // prints [This is a string slice]
}

2. Creating slices from an array

A slice has a reference to an array. So, it’s not difficult to create them from arrays. Here is how to do that.

array[lowerIndex:higherIndex]

Element high is excluded here.

package main

import "fmt"

func main() {
	var arr = [4]int{1, 2, 3, 4}
	var arrSlice = arr[1:3]
	
	fmt.Println(arrSlice)   //prints [2 3]
}

3. Creating slices from another slice

Slices can be created from other slices by taking a slice of that slice.

package main

import "fmt"

func main() {
	var odds =  [8]int{1, 3, 5, 7, 9, 11, 13, 15}
	slice1 := odds[2:]
	fmt.Println(slice1)     // prints [5 7 9 11 13 15]
	slice2 := slice1[2:4]
	fmt.Println(slice2)     // prints [9 11]
}

4. Creating slices using make() function

There is a function in Go called make(), which can be used to create slices as well. Which takes in type of slice, length, and capacity of that slice.

package main

import "fmt"

func main() {
	s := make([]int, 5) // make an int slice of length 5
	fmt.Println(s) // [0 0 0 0 0]
}

The len() and cap() functions

The len() and cap() functions provide the length and capacity of a slice. To understand the difference between both, let’s see an example.

package main

import "fmt"

func main() {
	s := []int{2, 4, 6, 8, 10}
	fmt.Println(len(s), cap(s))     // 5 5
	arr := [6]int{1, 2, 3, 4, 5, 6}
	arrSlice := arr[2:4]
	fmt.Println(len(arrSlice), cap(arrSlice))  // 2 4
}

Zero-valued slices

The zero-valued slice is nil. That means its length and capacity is zero. Here is an example showing it.

package main

import "fmt"

func main() {
	s := []int{}
	fmt.Println(len(s), cap(s))
}

Modifying values in slices

The modification of values inside slices is really simple. All we need to do is just assign data in that index or slice. Here is an example illustrating the ways it can be done.

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4}
	s[1] = 0
	fmt.Println(s)   // [1 0 3 4]
}

Removing values from slices

To remove value at index i in a slice we can simply append elements up to index i and from i+1 to the end. This is what it looks like.

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5, 6, 7, 8}
	//v := []int{}
	_ = append(s[:3], s[4:]...)    // remove 3rd elem
	fmt.Println(s)
}

Passing slice to a function

When a slice is passed to a function and made changes inside it, the changes will be available outside as well. The reason behind this is that the slice is a reference type.

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5, 6, 7, 8}
	PrintSlice(s)    // [1 2 3 4 5 6 7 8]
}

func PrintSlice(a []int) {
	fmt.Println(a)
}

Slice functions

There are slice functions that make using slice even easier. Here are some important ones.

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5, 6, 7, 8}
	var s2 = make([]int, 5)
	
	// append function
	s = append(s, 9, 10)
	
	fmt.Println(s)   // [1 2 3 4 5 6 7 8 9 10]
	
	// copy function
	ne := copy(s2, s) // returns number of elements copied
	fmt.Println(s2, ne)  // [1 2 3 4 5] 5
}

Slice of slices

We can create a slice of slices which is essentially a multidimensional slice.

package main

import "fmt"

func main() {
	mds := [][]int{
		{1, 2, 3},
		{4, 5, 6},
		{7, 8, 8},     // mandatory last comma
	}
	
	fmt.Println(mds)    // [[1 2 3] [4 5 6] [7 8 8]]
}

Iterating over a slice elements

Iteration over a slice can be done using a for-range loop. We can use simple for loop along with len function also. Here is how to do that.

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	
	for i, v := range s {
		fmt.Println(i, v)
	}
	
	// output: 
	// 0 1
	// 1 2
	// 2 3
	// 3 4
	// 4 5
	// 5 6
	// 6 7
	// 7 8
	// 8 9
}

This is how we can use slices in Go.