Working with array in Go

Thanh Pham / Mon 23 Sep 2019

Array in Go is just a data structure that hold a collection of elements of any type. Each element can be accessed by its index. Length of array is fixed at compile time and its size is a part of its type.

The type [n]T is an array of n values of type T. It can be declared as full declaration statement or in a short-hand format, with or without init values.

Array also can be declared in form of [...]T where its size will be determined by the compiler.

var holidays = [7]bool{}
seasons := [4]string{"Spring", "Summer", "Autumn", "Winter"}
weekDays := [7]int{1, 2, 3, 4, 5, 6, 7}
fruits := [...]string{"apple", "guava", "orange"} // type [3]string
visited := [10]bool{1: true, 3: true, 5: true, 7: true, 9: true}
sudoku := [9][9]int{}

Size of array is a part of its type and it is determined at the compile time

That means you cannot extend its size at run-time and cannot assign it to another type at run-time:

fruits := [...]string{"apple", "guava", "orange"} // type: [3]string
moreFruits := [4]string{"grapes"}                 // type: [4]string

moreFruits = fruits // compile error

Arrays are comparable if they have same type

firstArr := [3]int{1, 2, 3}    // type: [3]int
secondArr := [3]int{1, 2, 3}   // type: [3]int
thirdArr := [4]int{1, 2, 3, 4} // type: [4]int

fmt.Println(firstArr == secondArr) // true

fmt.Println(secondArr == thirdArr) // compile error

Each elements can be accessed by index or range over the array. Access index out of the array will cause a panic

var weekDays [7]string
weekDays[0] = "Sunday"
weekDays[1] = "Monday"
weekDays[2] = "Tuesday"
weekDays[3] = "Wednesday"
weekDays[4] = "Thursday"
weekDays[5] = "Friday"
weekDays[6] = "Saturday"

fmt.Println(weekDays[5])
fmt.Println("Days in a week:")
for _, day := range weekDays {
	fmt.Printf("\t%s\n", day)
}

// fmt.Println(weekDays[7]) // panic: index out of bound

Passing an array to a method will create a copy of the original array

This means what you do with the copied array will not affect to the original array.

package main

import "fmt"

func main() {
	fruits := [3]string{"apple", "orange"}
	addGuava(fruits) // doesn't change values of variable "fruits"
}

func addGuava(fruits [3]string) {
	fruits[2] = "guava"
}
Playground

Passing the pointer of the array to a function if you want to change its value in that function:

package main

import "fmt"

func main() {
	fruits := [3]string{"apple", "orange"}
	addGuava(&fruits) // change value of variable  "fruits"
}

func addGuava(fruits *[3]string) {
	fruits[2] = "guava"
}
Playground

Assign or range statement on an array will also create a copy of the original array

arr := [4]int{0, 1, 2, 3}
newArr := arr

fmt.Printf("%p != %p", &arr, &newArr) // 0xc000126000 != 0xc000126020
Playground

Interact with value of array while ranging over it will not affect the original value:

arr := [4]int{0, 1, 2, 3}
for _, v := range arr {
	v += 100 // will not affect the original array values
}
fmt.Println(arr) // [0, 1, 2, 3]
Playground

If you want to change value of original array while ranging over it, use index instead:

arr := [4]int{0, 1, 2, 3}
for i := 0; i < len(arr); i++ {
	arr[i] += 100
}
fmt.Println(arr) // [100 101 102 103]
Playground

Pointer of index and value inside range statement will be reused.

Notice that the pointers of i and v are the same in the result:

arr := [3]int{1, 2, 3}
for i, v := range arr {
	fmt.Printf("i=%d, v=%d, &i=%p, &v: %p\n", i, v, &i, &v) // i, v point to the same addresses for each iteration
}
Playground

This will cause a problem if you use goroutine inside the for loop as below. Notice that only the last element is printed.

arr := [3]int{1, 2, 3}
for i, v := range arr {
	go func() {
		fmt.Printf("i=%d, v=%d, &i=%p, &v: %p\n", i, v, &i, &v)
	}()
}
Playground

Define local variable to avoid the variables are captured is one way to avoid the above problem:

arr := [3]int{1, 2, 3}
for i, v := range arr {
	i, v := i, v
	go func() {
		fmt.Printf("i=%d, v=%d, &i=%p, &v: %p\n", i, v, &i, &v)
	}()
}
Playground

When do you use array?

Normally, array is used when the number of element is fixed at compile time. Example:

  • Used in parsing network package where the length of the package is fixed. Example: TCP, UDP, DHCP, DNS  packages, ...
  • Used in hashing, encryption algorithms: MD5, Base64, Base58,...
  • Represent a collection of fixed length elements like: days in a week, months in a year, ...
Next In
golang
Working with slice in Go

A quick review of slice in Go.