What is an array?
An array is a collection of values of the same type. For example, you can have an array of integers or an array of strings. Since Go is statically typed, one array cannot freely mix unrelated value types.
In Go, an array has a fixed length. Once you create an array with a particular size, that size cannot be increased or decreased. If you need a growable sequence, you usually want a slice, which we will discuss in the next lesson.
An array is a composite type because it is built from other types like
int,string, orbool.
How to declare an array?
An array is a type in itself. This type is defined like [n]T where n is the number of elements an array can hold and T is a data type like int or string.
So, to define a variable that stores 3 values of type int, we write it like this.
package main
import "fmt"
func main() {
var a [3]int
fmt.Println(a)
}
In this program, a is an array with 3 integer elements, but we have not assigned values to those elements yet. So what does it print?
Go fills each element with the zero value of its type. For int, the zero value is 0, so the program prints an array of 3 zeros.
[0 0 0]
Value assignment
We can assign values to individual array elements using their position, also called the index. Go array indexes start at 0, so the last index is n - 1, where n is the array length.
To access any element in the array, we need to use a[index] syntax where a is an array variable. So let’s take our earlier example and modify it a little.
package main
import "fmt"
func main() {
var a [3]int
a[0] = 1
a[1] = 2
a[2] = 3
fmt.Println("array a => ", a)
fmt.Println("elements => ", a[0], a[1], a[2])
}
// array a => [1 2 3]
// elements => 1 2 3
In this program, we assigned new values to all 3 elements in the array using a[index] syntax.
Initial value
Assigning each element one by one becomes painful when the array is large. Go gives us a shorter syntax for creating an array with initial values.
var a [n]T = [n]T{V1,V2,...,Vn}
For example, if the array values are 1, 2, and 3, we can write this.
var a [3]int = [3]int{1, 2, 3}
You can also drop the data type declaration from the left-hand statement and Go will infer the type from the array definition.
var a = [3]int{1, 2, 3}
Or you could use shorthand syntax :=, dropping var
a := [3]int{1, 2, 3}
There is absolutely no need to define all elements of an array. In this example, we could have defined the first two elements, leaving the third element a zero-value.
package main
import "fmt"
func main() {
a := [3]int{1, 2}
fmt.Println(a)
}
// [1 2 0]
Multi-line initial value
You can define an array with initial values over multiple lines but since these values are comma-separated, you need to make sure to add a comma at the end of the last element. Why? Read further.
package main
import "fmt"
func main() {
greetings := [4]string{
"Good morning!",
"Good afternoon!",
"Good evening!",
"Good night!", // must have comma
}
fmt.Println(greetings)
}
// [Good morning! Good afternoon! Good evening! Good night!]
Look carefully at the comma after the last element. In a multi-line array literal, that trailing comma is required. Without it, Go’s semicolon insertion rule would end the statement in the wrong place.
Automatic array length declaration
Sometimes we do not want to count the elements manually. Go lets us use the ... operator in place of n in [n]T, and the compiler calculates the length from the initial values.
package main
import "fmt"
func main() {
greetings := [...]string{
"Good morning!",
"Good afternoon!",
"Good evening!",
"Good night!",
}
fmt.Println(greetings)
}
// [Good morning! Good afternoon! Good evening! Good night!]
This program prints the same result because the compiler calculates the length as 4.
Find the length of an array
Go provides the built-in len function to get the length of many values, including arrays.
package main
import "fmt"
func main() {
greetings := [...]string{
"Good morning!",
"Good afternoon!",
"Good evening!",
"Good night!",
}
fmt.Println(len(greetings))
}
// 4
Array comparison
Remember that an array’s length is part of its type. [3]int and [4]int are different types, and [4]int is also different from [4]string. Go will not compare arrays of different types.
However, Go can compare [3]int with another [3]int because both arrays have the same type.
For two arrays to be equal, they must have the same type, the same elements, and the same element order. If any of those conditions fail, == returns false.
Go first checks the array type, then compares elements by index.
Let’s look at a simple example.
package main
import "fmt"
func main() {
a := [3]int{1, 2, 3}
b := [3]int{1, 3, 2}
c := [3]int{1, 1, 1}
d := [3]int{1, 2, 3}
fmt.Println("a == b", a == b)
fmt.Println("a == c", a == c)
fmt.Println("a == d", a == d)
}
// a == b false
// a == c false
// a == d true
So a, b, c and d, all of them have the same data type of [3]int. In the first comparison, a == b, since a and b both contain the same element but different order, this condition will be false. In the second comparison a == c, since c contains completely different elements than a, this condition will be false.
In the third comparison, a and d contain the same elements in the same order, so a == d is true.
Array iteration
To iterate over an array, we can use for loop.
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3, 4, 5}
for index := 0; index < len(a); index++ {
fmt.Printf("a[%d] = %d\n", index, a[index])
}
}
// a[0] = 1
// a[1] = 2
// a[2] = 3
// a[3] = 4
// a[4] = 5
In this example, we keep increasing index until it reaches len(a), and print each element by index.
This works, but it is a little noisy. Go’s range operator gives us the index and value directly while looping.
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3, 4, 5}
for index, value := range a {
fmt.Printf("a[%d] = %d\n", index, value)
}
}
// a[0] = 1
// a[1] = 2
// a[2] = 3
// a[3] = 4
// a[4] = 5
The range operator returns each element’s index and value. If we do not need the index, we can assign it to the blank identifier.
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3, 4, 5}
for _, value := range a {
fmt.Println(value)
}
}
// 1
// 2
// 3
// 4
// 5
Multi-dimensional arrays
When the elements of an array are also arrays, we get a multi-dimensional array. Since an array is a type, every inner array must have the same type.
The syntax is [n][m]T, where n is the number of outer elements and m is the number of elements in each inner array. In other words, the outer array contains n values of type [m]T.
package main
import "fmt"
func main() {
a := [3][2]int{
[2]int{1, 2},
[2]int{3, 4},
}
fmt.Println(a)
}
// [[1 2] [3 4] [0 0]]
Since we can use ... to infer the outer array length, this program can also be written like this.
package main
import "fmt"
func main() {
a := [...][2]int{
[...]int{1, 2},
[...]int{3, 4},
[...]int{5, 6},
}
fmt.Println(a)
}
// [[1 2] [3 4] [5 6]]
Go also lets us write multi-dimensional array literals in a shorter form.
package main
import "fmt"
func main() {
a := [3][2]int{{1, 2}, {3, 4}, {5, 6}}
fmt.Printf("Array is %v and type of array element is %T", a, a[0])
fmt.Println()
}
// Array is [[1 2] [3 4] [5 6]] and type of array element is [2]int
In this program, Go already knows each inner element is [2]int, so we do not need to repeat that type. We can also use ... like this.
a := [...][2]int{{1, 2}, {3, 4}, {5, 6}}
Iterating over a multi-dimensional array is the same idea as iterating over a simple array. The only difference is that each value is another array, so we usually use a nested loop.
for _, child := range parent {
for _, elem := range child {
...
}
}
Passed by value
When you pass an array to a function, Go passes it by value, just like int or string. The function receives a copy. If you change that copy inside the function, the original array does not change.
This matters because slices behave differently, as we will see in the next lesson.