Golang Tutorials - Beginner guide Slice Examples
This blog post covers Golang Slice Complete tutorials with example
Golang Slice Introduction
Arrays are a static fixed size. Slices are dynamically sized, It means arrays once created can not change their size. Slices can change the 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 its data and uses internal an array
- Internally Slices uses Array point as a reference to it, has more power, and is 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
An empty slice can be created with empty data assigned to it. This is used to represent empty collections like no results found for database queries
emptySlice:= []int{} // variable value is []
Here variable is declared with initialized with empty values. The 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
The Nil
slice is created using empty length and type. A slice created with the value not initialized is also called slice nil.
Here internal array is not created.
This will be used to represent a slice that does not exist inside a function call.
var variable []int //// variable value is nil
The 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))
}
The output of the above program is
[] true 0 0
Create and initialize Slice using literal
This is one of the ways of creating a slice with literal syntax. Here is the syntax of a 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 syntax.
The right-hand side contains Slice literals. Literal is an expression, each of which specifies a slice element, enclosed in brackets []
. When a variable is declared, Internally, a variable is created and assigned with these values. Here length is empty, the compiler infers the length from many elements of the slice.
The above slice literal is rewritten using shorthand variable declaration syntax
strs := []string{"one", "two", "three"}
Here short assignment operator -:= is used by omitting the var keyword.
Following is an example of using slice literals creation
package main
import (
"fmt"
)
func main() {
// Slice Creation using slice literal
var strs = []string{"one", "two", "three"}
fmt.Println(strs)
// Slice Creation 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 - of 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 specifying low and high separated with a colon symbol. low
specifies the starting index of a slice, and high
is the 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 values 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 a 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 a slice from the existing slice. This will be useful when you want to create a part of a slice and assign it to another 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)
}
The 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 the in-built make() function. Here is the syntax of make() function
func make([]T, len, cap) []T
This accepts the datatype array, length, and capacity creates an array internally, and returns a slice that references an internal array. Capacity is optional. Based on the first type of the argument, non-zero values are printed (for numeric - 0, String -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 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 the 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
The slice length can be extended by reducing its length. if it extended more than the existing capacity, It throws a runtime exception following is an example of 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 the 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 an array as many iterations are executed over the length of the 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 returns two elements, the first element is an index, and the second is the actual element value if a slice is 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 a blank identifier Each iteration has an index and value, if you don’t want one of these, you can replace it with a blank identifier (_). The compiler treats 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 i.e. minimum of len(source) and len(destination). destination slice should have sufficient capacity to copy its elements
Copy slice to another slice
This copies the 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
The slice copy function can also be used to copy string bytes to a 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 the end element of Slice
Slice is the dynamic size and changes its length at runtime. The append function is an inbuilt function in Slice that adds the element end of the slice. Here is a signature of the Append function
func append(inputslice []T, args ...T) []T
This function takes input slice elements args …T - This is a variadic function that contains multiple arguments and returns a new slice of all elements including existing elements. if there is enough capacity available in the underline array, the element is added end of the last element, and the length is incremented. if there is not enough capacity available, a new array will be created, all the existing values are copied to the new array, and new elements are added at the end of existing elements, a new array is referenced by the 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 have a capacity of four, when you are appending more elements, it can’t grow its size.
The new underline array is created with a bigger size copies existing elements and appends new elements. The new slice has a capacity of 8. The original slice capacity is 3 only.
Append slice to another slice
once slice can be appended to another 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 the append function, we can append a string to a 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 of elements in Golang
A slice is a reference to an internal array and does not have any data on its own. Any modifications were done to the slice change 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, and create a new slice by copying index 2,3 from the original slice. Iterated the new slice using a range loop and incremented its original value. Observed incremented values in an Original slice
multidimensional slice - a slice of slices
Like arrays, Slices can be of multidimensional types. Normal slice elements can be of any type. Each type can contain slices also. It 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 the 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