Learn Golang Tutorials - Beginner guide Slice Examples


This blog post covers Golang Slice Complete tutorials with example

Golang Slice Introduction

Arrays are static fixed size. Slices are dynamically sized, This means arrays once created can not change its size. Slice can change size and 

It gives more power  and flexibility compared with Arrays

I already posted an article on Arrays in Golang. 

Key points of Slice 

  • Slice is a dynamic array that can increase its size
  • Slices are similar to Arrays in other programming language-go
  • Slice does not contain own data and uses an array internally
  • Internally Slices uses Array point a reference to it,  have more power and flexible
  • Slices elements are indexable

Slice Variable Create  and Initialize

There are many ways we can create a Slice variable and initialize it

Slice Empty Values

empty slice can be created with empty data assigned to it. This is used to represent empty collection like no results found for database queries

emptySlice:= []int{} // variable value is []  

Here variable is declared with initialized with empty values. Here internal array is created Empty Slice returns zero for len() and cap() functions.Here is a complete example of Slice Empty with zero values.

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 var emptySlice = []int{}  
 fmt.Println(emptySlice, emptySlice == nil, len(emptySlice), cap(emptySlice))  
  
}  

The output of the above program is

[] false 0 0  

Nil Slice non zero values

Nil slice is created using empty length and type. Slice created with the value not initialized and it is called slice nil. Here internal array is not created

This will be used to represent a slice that does not exist inside a functions call.

var variable []int  //// variable value is nil  

Nil slice always returns zero for length and capacity. Here is a complete example of Slice Nil with zero values

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 var nilSlice []int  
 fmt.Println(nilSlice, nilSlice == nil, len(nilSlice), cap(nilSlice))  
  
}  

An output of the above program is

[] true 0 0  
  

Create and initialize Slice using literal

This is one of the way creating a slice with literal syntax Here is a syntax of slice literal

// Slice Creation using slice literal  
var strs = []string{"one", "two", "three"}  
fmt.Println(strs) //[one two three]  

Here we create slice strings using slice literals. Right-hand side contains Slice literals. Literal is an expression, each of which specifies a slice element, enclosed in brackets []. When a variable is created literals. variable created and assigned with this values. Here length is empty, the compiler infers the length from a number of elements of the slice. The above slice literal is rewritten using shorthand variable declaration syntax

strs := []string{"one", "two", "three"}  

here short assignment operator - := used by omitting var keyword.
Following is an example of using slice literals creation

package main  
  
import (  
 "fmt"  
)  
func main() {  
 // Slice Creaation using slice literal  
 var strs = []string{"one", "two", "three"}  
 fmt.Println(strs)  
 // Slice Creaation using shorthand variable declaration  
 strs1 := []string{"one", "two", "three"}  
 fmt.Println(strs1)  
}  

Output is

[one two three]  
[one two three]  

Create a slice from an array - low and high expression 

Slice can be created using a segment of an array. Slice is created with low and high indexes separated by a colon.
Here is a syntax

k[low:high]  

Slice k is created using an array with specifying low and high separated with colon symbol low specifies starting index of a slice high is end index of a slice ie length of an array -1 for example

array := [5]int{1,2,3,4,5}  
s1:= array[0:5] //  [1,2,3,4,5]  

The above line creates a slice from an array. The slice contains all the value of an array starting from low=0 to high=len() -1.

s2:= array[1:3] //  [2,3]  

low and high indexes are optional. default values of low are always zero and high is the length of an array -1 The same can be rewritten by omitting low and high indexes

array[0:] same as  array[0:len(array)]  
array[:5] same as  array[0:5]  
array[:] same as  array[0:len(array)]  

Following is a complete example creation of slice from an array

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 array := [6]int{1, 2, 3, 4, 5, 6} // array creation  
 s1 := array[1:5] // Slice creation from array  
 s2 := array[:2] // Slice creation from array  
 s3 := array[1:] // Slice creation from array  
 s4 := array[:] // Slice creation from array  
 fmt.Println("oringal array: ", array)  
 fmt.Println("s1 = ", s1)  
 fmt.Println("s2 = ", s2)  
 fmt.Println("s3 = ", s3)  
 fmt.Println("s4 = ", s4)  
  
}  

Output is

oringal array:  [1 2 3 4 5 6]  
s1 =  [2 3 4 5]  
s2 =  [1 2]  
s3 =  [2 3 4 5 6]  
s4 =  [1 2 3 4 5 6]  

Slice creation using other Slice

This is another way of creating slice from existing slice. This will be useful when you want to create a part of slice and assign to other slice

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 originalSlice := []string{"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"}  
  
 copySlice1 := originalSlice[2:]  
 copySlice2 := copySlice1[1:3]  
 copySlice3 := originalSlice[:]  
 copySlice4 := originalSlice[:4]  
  
 fmt.Println("originalSlice : ", originalSlice)  
 fmt.Println("copySlice1 : ", copySlice1)  
 fmt.Println("copySlice2 : ", copySlice2)  
 fmt.Println("copySlice3 : ", copySlice3)  
 fmt.Println("copySlice4 : ", copySlice4)  
}  

An output of the above program is

originalSlice :  [one two three four five six seven eight nine ten]  
copySlice1 :  [three four five six seven eight nine ten]  
copySlice2 :  [four five]  
copySlice3 :  [one two three four five six seven eight nine ten]  
copySlice4 :  [one two three four]  

Create a slice using make() function 

Slice can be created using in-built make() function Here is an syntax of make() function

func make([]T, len, cap) []T  

This accepts datatype array, length, and capacity and creates array internally and return slice which references to an internal array. Capacity is optional. Based on the first type of the argument, non zero values are printed (for numeric - 0, String -empty space) for example

slice1 := make([]int, 4)  
fmt.Printf("length=%d capacity=%d slice=%v\n",len(slice1), cap(slice1), slice1) // length=4 capacity=4 slice=[0 0 0 0]  

This creates a slice with array integer non zero values, length=4 and capacity=4, when capacity is not specified and the default is equal to length The capacity is supplied, the Underlying array is created with capacity 6 and data is stored up to length =3

slice2 := make([]int, 3, 6)  
fmt.Printf("length=%d capacity=%d slice=%v\n",len(slice2), cap(slice2), slice2) //length=3 capacity=6 slice=[0 0 0]  

A complete example of slice make a function

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 slice1 := make([]int, 4)  
 fmt.Printf("length=%d capacity=%d slice=%v\n",  
  len(slice1), cap(slice1), slice1)  
 slice2 := make([]int, 3, 6)  
 fmt.Printf("length=%d capacity=%d slice=%v\n",  
  len(slice2), cap(slice2), slice2)  
 slice3 := slice2[:2]  
 fmt.Printf("length=%d capacity=%d slice=%v\n",  
  len(slice3), cap(slice3), slice3)  
  
}  

Output is

length=4 capacity=4 slice=[0 0 0 0]  
length=3 capacity=6 slice=[0 0 0]  
length=2 capacity=6 slice=[0 0]  

Length and capacity slice - len() capacity() function 

Golang has built-in functions like len() and capacity() functions Slice does not hold its own data, It is a reference or pointer to an underlying internal array. len() function- length is the number of elements in a slice cap function - capacity is the number of elements in the underlying array which counts from starting index

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 // Slice Creation using slice literal  
 var strs = [8]string{"one", "two", "three", "four", "five", "six", "seven", "eight"}  
  
 s1 := strs[1:3]  
 displaySlice(s1)  
  
}  
  
func displaySlice(s []string) {  
 fmt.Printf("  %v length:%d capacity:%d\n", s, len(s), cap(s))  
}  

Output is

[two three] length:2 capacity:7  

Slice length can be extended by reslicing it’s length. if it extended more than existing capacity, It throws runtime exception following is an example for extending/reslice example by changing its length

  
  
package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 // Slice Creation using slice literal  
 var strs = []string{"one", "two", "three", "four", "five", "six", "seven", "eight"}  
 displaySlice(strs)  
  
 // Empty Slice  
 s1 := strs[:0]  
 displaySlice(s1)  
  
 // Shirnk slice length.  
 s2 := strs[:4]  
 displaySlice(s2)  
  
 // Remove first three values  
 s3 := strs[3:]  
 displaySlice(s3)  
}  
  
func displaySlice(s []string) {  
 fmt.Printf("%v length:%d capacity:%d\n", s, len(s), cap(s))  
}  

Output is

[one two three four five six seven eight] length:8 capacity:8  
[] length:0 capacity:8  
[one two three four] length:4 capacity:8  
[four five six seven eight] length:5 capacity:5  

Iteration of elements in slice 

Like Array, Elements are iterated using for loop and for with range keyword

Iterate elements in a slice - for loop 

This iteration works like array as a number of iterations are executed over length of slice.

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 numbs := []string{"one", "two", "three", "four"}  
 for i := 0; i < len(numbs); i++ {  
  fmt.Println(numbs[i])  
 }  
}  

output is

one  
two  
three  
four  

Iteration of the element in slice using for loop with range keyword 

With a range for loop, Each iteration return two elements, the first element is an index, second is the actual element value if a slice is a nil, zero returns are evaluated.

package main  
  
import (  
 "fmt"  
)  
  
func main() {  
 numbs := []string{"one", "two", "three", "four"}  
 for index, numb := range numbs {  
  fmt.Printf("%d = %s\n", index+1, numb)  
 }  
}  

Output is

1 = one  
2 = two  
3 = three  
4 = four  

You can omit either index or value in for range loop using blank identifier each iteration has index and value, if you don’t want one of this, you can replace with a blank identifier (_). Compiler treat that this value is not required The same can be rewritten with a blank identifier as

func main() {  
 numbs := []string{"six", "seven", "eight", "nine"}  
 for _, numb := range numbs {  
  fmt.Printf("%s\n", numb)  
 }  
}  

Output is

six  
seven  
eight  
nine  

Copy function - Copy elements in a slice 

copy() is an inbuilt function of slice, copies elements from one slice to another slice

func copy(destination, source []T) int  

This function has two arguments of type slice all of the source elements are copied to destination elements if elements already exist, overwrites the elements. It returns the number of elements copied ie minimum of len(source) and len(destination). destination slice should have sufficient capacity to copy its elements

Copy slice to another slice 

This copies src and destination slices and returns the destination slice

package main  
  
import "fmt"  
  
func main() {  
 destination := make([]string, 4)  
 source := []string{"one", "two", "three", "four"}  
 fmt.Println("source: ", source)  
 fmt.Println("destination: ", destination)  
 output := copy(destination, source)  
 fmt.Println("Number of elements copied = ", output)  
 fmt.Println("Output of Copy  = ", destination)  
  
}  

Output is

source:  [one two three four]  
destination:  [   ]  
Number of elements copied =  4  
Output of Copy  =  [one two three four]  

Copy string bytes to byte slice example 

Slice copy function can also be used to copy string bytes to slice of bytes

package main  
  
import "fmt"  
  
func main() {  
  
 var destination = make([]byte, 5)  
 source := "Test string"  
  
 fmt.Println("source: ", source)  
 fmt.Println("destination: ", destination)  
 output := copy(destination, source)  
  
 fmt.Println("Number of elements copied = ", output)  
 fmt.Println("Output of Copy  = ", destination)  
  
}  

Output is

source:  Test string  
destination:  [0 0 0 0 0]  
Number of elements copied =  5  
Output of Copy  =  [84 101 115 116 32]  

Append function - add an element to end element of Slice 

Slice is the dynamic size and changes its length at runtime. Append function is an inbuilt function in Slice which adds element end of the slice. Here is a signature of Append function

func append(inputslice []T, args ...T) []T  

This function takes input slice elements args …T - this is variadic functions which contains multiple arguments and return new slice of all elements including existing elements if there enough capacity available in underline array, the element is added end of last element and length is incremented if there is not enough capacity available ,new array will be created, all the existing values are copied to new array, and new elements are added at end of existing elements, new array is referenced by slice and returned

package main  
  
import "fmt"  
  
func main() {  
 numbs := []string{"one", "two", "three", "four"}  
  
 output := append(numbs, "five", "six", "seven")  
 fmt.Printf(" %v, length = %d, capacity = %d\n", numbs, len(numbs), cap(numbs))  
 fmt.Printf(" %v, length = %d, capacity = %d\n", output, len(output), cap(output))  
 numbs[0] = "newone"  
 numbs[1] = "newtwo"  
 fmt.Printf(" %v, length = %d, capacity = %d\n", numbs, len(numbs), cap(numbs))  
 fmt.Printf(" %v, length = %d, capacity = %d\n", output, len(output), cap(output))  
  
}  
  

Output is

 [one two three four], length = 4, capacity = 4  
 [one two three four five six seven], length = 7, capacity = 8  
 [newone newtwo three four], length = 4, capacity = 4  
 [one two three four five six seven], length = 7, capacity = 8

In the above example slice numbs has a capacity of four, when you are appending more elements, it can’t grow its size. The new underline array is created with bigger size and copy existing elements and append new elements New slice has a capacity of 8. original slice capacity is 3 only.

Append slice to another slice 

once slice can be appended to other slice using three dots notation (…)operator Output of append function result is not overlapped

package main  
  
import "fmt"  
  
func main() {  
  
 s1 := []string{"one", "two", "three"}  
 s2 := []string{"four", "five", "six"}  
  
 s3 := append(s1, s2...)  
  
 fmt.Println("s1 = ", s1)  
 fmt.Println("s2 = ", s2)  
 fmt.Println("Output append = ", s3)  
  
}  

Output is

s1 =  [one two three]  
s2 =  [four five six]  
Output append =  [one two three four five six]  

Append string bytes to Slice bytes 

Using append function(), we can append a string to slice of bytes.

package main  
  
import "fmt"  
  
func main() {  
  
 s1 := []byte("one")  
 s2 := "six"  
  
 s3 := append(s1, s2...)  
  
 fmt.Println("s1 = ", s1)  
 fmt.Println("s2 = ", s2)  
 fmt.Println("Output append = ", s3)  
  
}  

output is

s1 =  [111 110 101]  
s2 =  six  
Output append =  [111 110 101 115 105 120]  

Modify a slice elements 

Slice is a reference to an internal array and has not any data on its own. Any modifications done to slice will be changed in an internal array

package main  
  
import "fmt"  
  
func main() {  
 slice := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}  
 newslice := slice[2:4]  
 fmt.Println("Before Modification", slice)  
 for k := range newslice {  
  newslice[k]++  
 }  
 fmt.Println("After Modification", slice)  
  
}  

output is

Before Modification [1 2 3 4 5 6 7 8 9 0]  
After Modification [1 2 4 5 5 6 7 8 9 0]  

Create a slice with 10 elements, created new slice from copying indexes 2,3 from original slice Iterated new slice using range loop and incremented its original value. Observed incremented values in an Original slice

multidimensional slice - slice of slices

Like arrays, Slices can be of multidimensional types. Normal slice elements can be of any type. Each type can contains slices also. This works like same as arrays Following is an example of multidimensional slices

package main  
  
import "fmt"  
  
func main() {  
 multiSlice := [][]string{  
  {"one", "two", "three"},  
  {"four", "five", "six"},  
  {"seven", "eight", "nine"},  
  {"ten", "eleven", "Twelve"},  
 }  
  
 fmt.Println("Slice of slice  :", multiSlice)  
 fmt.Println("length : ", len(multiSlice))  
 fmt.Println("capacity : ", cap(multiSlice))  
}  

When above program is compiled and output is as follows

Slice of slice  : [[one two three] [four five six] [seven eight nine] [ten eleven Twelve]]  
length :  4  
capacity :  4  

Similar Posts