Sebastian Gomez
Arrays and Loops in Go
Arrays in Go
Arrays in Go are a data structure used to store a set of values of the same type. An array is an ordered sequence of elements that share the same type. In Go an array has a fixed size that is defined at compile time.
For example, the following code creates an array of integers of size 3:
var arr [3]intSo it can hold at most 3 elements of type integer.
Now, very often we do not know in advance how many elements we are going to need, and for that Go has slices. A slice is written []T (with no number between the brackets) and represents a variable size view over a sequence of elements. This is the key distinction: [N]T is a fixed size array, while []T is a slice, which can grow and shrink. A slice is declared like this:
// A slice of strings (variable size)
var arr2 []stringThe elements of an array can be accessed using their index, which is the number of the element's position in the array. Indexes start from 0. For example, the following code assigns the value 5 to the first element of the array above:
arr[0] = 5Arrays can also be initialized with predefined values. For example, the following code creates an array of integers of size 3 with the values 5, 10 and 15:
var arr = [3]int{5, 10, 15}Go lets us insert elements after the last element using the append function, but only on slices. On fixed size arrays we can only assign values using the index.
// This is how we add elements to a slice
arr2 = append(arr2, "hola")We need to keep a few things in mind, let's look at the following example:
package main
import "fmt"
func main() {
var arr [3]int
arr[0] = 5
fmt.Println(arr)
// This prints [5 0 0]
// This is not allowed because arr is a fixed-size array, not a slice
// arr = append(arr, 3)
// A slice of strings (variable size)
var arr2 []string
// This is how we add elements to the slice
arr2 = append(arr2, "hola")
fmt.Println(arr2)
// If index 88 has not been filled yet, the next line triggers a runtime panic
// arr2[88] = "helloworld"
fmt.Println(arr2)
}Accessing the values of an array when it is very large starts to cause problems, so that is where cyclic structures begin to matter, and therefore they are worth studying.
Cyclic structures in Go
### The For structure
The for loop is the most commonly used loop in Go. It is used to iterate over a sequence of elements, based on conditions. The syntax of for in Go is as follows:
for [initialization]; [condition]; [increment] { // code to run }+---------------------+
| For Loop |
+---------------------+
| |
| Initialization | (Optional)
| for i := 0; |
| |
+---------------------+
| |
| Condition | (Required for conditional loops)
| i < 10; |
| |
+---------------------+
| |
| Post-Execution | (Optional)
| i++ |
| |
+---------------------+
| |
| Code |
| Block | (The code that runs on each iteration)
| |
+---------------------+In its simplest form, a for statement specifies the repeated execution of a block while a boolean condition evaluates to true. The condition is evaluated before each iteration. If the condition is absent, it is equivalent to the boolean value true.
- Single condition:
for a < b { a *= 2 }runs the block whileais less thanb. - For clause:
for i:= 0; i < 10; i++ { f(i) }initializesiat 0, and runsf(i)whileiis less than 10, incrementingiby one each iteration. - Range clause: used to iterate over the elements of a data structure such as an array or a slice.
package main
import "fmt"
func main() {
var arr = [3]int{5, 10, 15}
// Both blocks are similar: i holds the array index
// and v holds the value of the array element
for i, v := range arr {
fmt.Println(i, v)
}
for i := 0; i < len(arr); i++ {
fmt.Println(i, arr[i])
}
/* In this case, both loops will print:
0 5
1 10
2 15
*/
}This is the link to the official Go documentation that covers the for loop: go.dev/ref/spec#For_statements.
### The while loop
The while loop is a control structure used to run a block of code repeatedly while a condition holds. Go does not define the keyword while and its behavior is achieved through the language's for keyword.
Normally in other languages such as Java, JavaScript and C this would be the syntax:
while [condition] { // code to run }but in Go it would be:
for [condition] { // code to run }An example of its use would be:
func ejemploCicloWhile() {
// Declaring a variable to count
var i int = 0
// Using the for loop to iterate 5 times as if it were a while
for i < 5 {
fmt.Println("Contador:", i)
i++
}
}The code above will print the following:
Contador: 0
Contador: 1
Contador: 2
Contador: 3
Contador: 4### The do while loop
The do while loop is a control structure used to run a block of code repeatedly until a condition holds, but running the first block of code before evaluating its condition. Its syntax is:
do { // code to run } while [condition];But as you may know, in Go there is no while keyword, let alone a do keyword, so we have to fall back on for to emulate this behavior. An example of its use would be:
var j int = 0
// Emulating the do-while loop
for {
fmt.Println("Contador:", j)
j++
if j > 4 {
break
}
}The code above will print the following:
Contador: 0
Contador: 1
Contador: 2
Contador: 3
Contador: 4Note: The main difference between a while loop and a do-while loop lies in when the condition is evaluated for the loop's execution. In both cases they are flow control structures used to repeat a block of code based on a condition, but the way they handle that condition differs.
- Typical use of while: when you want to repeat a block of code while a condition is true, but it is not necessary for the block to run at least once.
- Typical use of do while: when you need the block of code to run at least once before evaluating whether the loop should continue.
But remember that the while and do keywords do not exist in Go, so you must achieve this behavior using for.
Operations on arrays in Go
Let's look now at the most basic operations on arrays, which consist of adding and removing elements, finding the index of an element and sorting arrays in ascending and descending order:
func operacionesArreglos() {
// We create a slice of integers
numeros := []int{1, 2, 3}
// We add an element to the slice
numeros = append(numeros, 4)
fmt.Println(numeros) // [1, 2, 3, 4]
// Remove the last element
numeros = numeros[:len(numeros)-1]
fmt.Println(numeros) // [1, 2, 3]
// Remove the first element
numeros = numeros[1:]
fmt.Println(numeros) // [2, 3]
// Remove the element at position 1
numeros = append(numeros[:1], numeros[2:]...)
fmt.Println(numeros) // [2]
// Remove the element at position 0
numeros = append(numeros[:0], numeros[1:]...)
fmt.Println(numeros) // []
// Let's fill the slice again with 5 numbers
numeros = []int{1, 6, 3, 4, 2}
// Search for the element 3 in the slice
index := 0
for index < len(numeros) {
if numeros[index] == 3 {
break
}
index++
}
fmt.Println(index) // 2
// Sort the array from highest to lowest (descending)
ordenarMayor(numeros, len(numeros))
// Sort the array from lowest to highest (ascending)
ordenarMenor(numeros, len(numeros))
}
/* The ordenarMayor() function takes the slice and sorts its elements from highest to lowest.
It receives two arguments: the first is a slice of type int and the second is the number
of elements, which is also of type int. */
func ordenarMayor(listNum []int, Cant int) {
tmp := 0
for x := 0; x < Cant; x++ {
for y := 0; y < Cant; y++ {
if listNum[x] > listNum[y] {
tmp = listNum[x]
listNum[x] = listNum[y]
listNum[y] = tmp
}
}
}
fmt.Print("\nArray sorted from highest to lowest: ")
for i := 0; i < Cant; i++ {
fmt.Print("[", listNum[i], "]")
}
fmt.Println()
}
func ordenarMenor(listNum []int, Cant int) {
tmp := 0
for x := 0; x < Cant; x++ {
for y := 0; y < Cant; y++ {
if listNum[x] < listNum[y] {
tmp = listNum[y]
listNum[y] = listNum[x]
listNum[x] = tmp
}
}
}
fmt.Print("\nArray sorted from lowest to highest: ")
for i := 0; i < Cant; i++ {
fmt.Print("[", listNum[i], "]")
}
fmt.Println()
}Note: these ordenarMayor / ordenarMenor are hand rolled sorts with two nested loops, meaning they have O(n²) complexity and redundant comparisons. They are useful only for educational purposes. In real code I recommend using sort.Ints from the standard library (you will see it in exercise 5), which is much more efficient.
The difference between = and :=
In Go, the = and := operators have different purposes and are used in different contexts.
Assignment `=`: used to assign values to existing variables. That is, it is used when the variable has been previously declared and only needs to be assigned (or reassigned) a value.
var x int
x = 10 // Assigning the value 10 to the variable xShort declaration `:=`: a short and convenient form in Go to declare and assign a variable in a single line. This operator declares the variable with the data type inferred from the assigned value, and simultaneously assigns that value to it. It is used when creating a new variable, and Go automatically infers the type based on the assigned value.
x := 10 // Declares x as int and assigns the value 10Let's look at some examples of correct and incorrect usage:
// Correct use of =
var a int
a = 5 // Correct, because a was already declared
// Incorrect use of =
a = 5 // Incorrect if a has not been declared previously
// Correct use of :=
a := 5 // Correct, declares a as int and assigns it 5
// Incorrect use of :=
var a int
a := 5 // Incorrect, a was already declaredIn short, = is used to assign values to already declared variables, while := is used to declare new variables and assign them values in a single step, with the type determined automatically by the assigned value.
Solved exercises to practice
Below are 10 classic exercises with arrays in Go and their respective solution, explained step by step:
1. Write a program in Go to print all the elements of an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// iterate over the array
for _, num := range arr {
fmt.Println(num)
}
}2. Write a program in Go to find the sum of all the numbers in an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// initialize the sum at 0
sum := 0
// iterate over the array
for _, num := range arr {
sum += num
}
fmt.Println("The sum of the array elements is", sum)
}3. Write a program in Go to find the maximum of an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// initialize the maximum with the first element of the array
// (important: do not initialize it at 0, because with negative numbers
// it would return 0, which is not in the array)
max := arr[0]
// iterate from the second element
for _, num := range arr[1:] {
if num > max {
max = num
}
}
fmt.Println("The maximum element of the array is", max)
}4. Write a program in Go to find the index of an element in an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// declare the element to search for
element := 4
// initialize the index
index := -1
// iterate over the array
for i, num := range arr {
if num == element {
index = i
break
}
}
fmt.Println("The index of element", element, "is", index)
}5. Write a program in Go to sort the elements of an array:
package main
import (
"fmt"
"sort"
)
func main() {
// declare array
arr := []int{3, 6, 2, 1, 4, 9, 7, 8, 5, 10}
// sort the array
sort.Ints(arr)
fmt.Println("Sorted array:", arr)
}6. Write a program in Go to remove an element from an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// declare the element to remove
element := 5
// initialize the index
index := -1
// iterate over the array
for i, num := range arr {
if num == element {
index = i
break
}
}
// remove element from the array
if index != -1 {
arr = append(arr[:index], arr[index+1:]...)
}
fmt.Println("Array after removing element:", arr)
}7. Write a program in Go to count the number of times an element repeats in an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 1, 4, 1, 5, 6, 7, 8, 9, 10, 1}
// declare the element to search for
element := 1
// initialize the counter
count := 0
// iterate over the array
for _, num := range arr {
if num == element {
count++
}
}
fmt.Println("The element", element, "repeats", count, "times.")
}8. Write a program in Go to insert an element at a specific position in an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// declare the element and the position
element := 11
position := 5
// insert the element
arr = append(arr, 0)
copy(arr[position+1:], arr[position:])
arr[position] = element
fmt.Println("Array after inserting element:", arr)
}9. Write a program in Go to reverse the elements of an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// reverse the elements
for i, j := 0, len(arr)-1; i < j; i, j = i+1, j-1 {
arr[i], arr[j] = arr[j], arr[i]
}
fmt.Println("Reversed array:", arr)
}10. Write a program in Go to remove the duplicate elements from an array:
package main
import "fmt"
func main() {
// declare array
arr := []int{1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 9, 10}
// initialize a new slice
newArr := []int{}
// iterate over the array
for _, num := range arr {
// check whether the element already exists in the new slice
isExist := false
for _, newNum := range newArr {
if num == newNum {
isExist = true
break
}
}
// add the element if it does not exist
if !isExist {
newArr = append(newArr, num)
}
}
fmt.Println("Array without duplicate elements:", newArr)
}Proposed exercises
Below I leave you 10 more exercises so you can practice loops in Go and send your solution as a Pull request to this repository: Go Para Principiantes.
- Write a program in Go that prints the first 10 natural numbers.
- Write a program in Go that computes the sum of the first 10 natural numbers.
- Write a program in Go that computes the average of the first 10 natural numbers.
- Write a program in Go that computes the factorial of a given number.
- Write a program in Go that determines whether a given number is even or odd.
- Write a program in Go that determines whether a given number is prime.
- Write a program in Go that prints the numbers from 1 to 100.
- Write a program in Go that determines the sum of the numbers from 1 to 100.
- Write a program in Go that determines whether a given number is within a given range.
- Write a program in Go that computes the number of digits of a given number.
Summary in 3 points
- In Go,
[N]Tis a fixed size array and[]Tis a variable size slice; only slices supportappend. - Go only has the
forkeyword, with it you cover the while and do while cases that in other languages are separate keywords. - Use
:=to declare and assign a new variable (with inferred type) and=to reassign a variable that already exists.
That's all, I hope this post is useful to you and that you can apply it to some project you have in mind, or that it simply helped you better understand arrays and loops in Go.
Leave me a comment if it helped you, if you want to add an opinion or if you have any questions. And remember that if you liked it, you can also share it using the social media links below. Good luck!
Sebastian Gomez
Creador de contenido principalmente acerca de tecnología.