Arrays
An array is a numbered sequence of elements of one type with a fixed length that's part of its type: [5]int and [6]int are different types. In everyday Go you'll use slices (next lesson) far more often, but slices are built on arrays, and arrays are the right tool for small fixed-size data such as coordinates, RGB colours or a chess board.
Declaring arrays
package main import "fmt" func main() { var scores [5]int // five zeros scores[0] = 90 scores[4] = 75 fmt.Println(scores, len(scores)) primes := [6]int{2, 3, 5, 7, 11, 13} fmt.Println(primes[2], primes[len(primes)-1]) weekdays := [...]string{"Mon", "Tue", "Wed", "Thu", "Fri"} // length counted for you fmt.Println(len(weekdays), weekdays) sparse := [5]string{1: "one", 3: "three"} // set specific indexes fmt.Printf("%q\n", sparse) }
[90 0 0 0 75] 5 5 13 5 [Mon Tue Wed Thu Fri] ["" "one" "" "three" ""]
Elements you don't set get the zero value. With [...] the compiler counts the elements and fixes the length. Indexes start at 0, so the last element is at len(a)-1.
Bounds checking
Go checks every index. A constant index that's out of range is a compile error; an out-of-range index computed at run time causes a panic instead of silently reading other memory:
package main func main() { var a [3]int a[5] = 1 }
./main.go:5:4: invalid argument: index 5 out of bounds [0:3]
package main import "fmt" func main() { a := [3]int{10, 20, 30} for i := 0; i <= len(a); i++ { // off by one: <= should be < fmt.Println(a[i]) } }
10 20 30 panic: runtime error: index out of range [3] with length 3 goroutine 1 [running]: … exit status 2
Arrays are values
Assigning an array or passing it to a function copies all of its elements. Changing the copy leaves the original untouched:
package main import "fmt" func double(nums [3]int) { for i := range nums { nums[i] *= 2 } fmt.Println("inside:", nums) } func main() { a := [3]int{1, 2, 3} b := a // a full copy b[0] = 100 fmt.Println(a, b) double(a) fmt.Println("after:", a) }
[1 2 3] [100 2 3] inside: [2 4 6] after: [1 2 3]
This is different from many languages, where arrays are references. Copying is cheap for small arrays but wasteful for big ones — another reason slices are usually preferred.
Comparing arrays
Arrays of the same type can be compared with ==, which checks every element. That also means they can be used as map keys:
package main import "fmt" func main() { a := [3]int{1, 2, 3} b := [3]int{1, 2, 3} fmt.Println(a == b, a != [3]int{3, 2, 1}) visited := map[[2]int]bool{} // grid positions as keys visited[[2]int{0, 0}] = true visited[[2]int{2, 5}] = true fmt.Println(visited[[2]int{2, 5}], visited[[2]int{1, 1}]) }
true true true false
Multi-dimensional arrays
An array of arrays makes a grid:
package main import "fmt" func main() { var board [3][3]rune for r := range board { for c := range board[r] { board[r][c] = '.' } } board[1][1] = 'X' board[0][2] = 'O' for _, row := range board { fmt.Println(string(row[:])) } }
..O .X. ...
row[:] turns the array into a slice of all its elements, which string() can then convert. You'll learn about slicing in the next lesson.
When to use arrays
- The size is genuinely fixed and small:
[3]float64for a 3-D point,[4]bytefor an IPv4 address,[32]bytefor a SHA-256 hash. - You want a comparable value to use as a map key.
- Everything else — lists that grow, data read from input, function parameters — should be a slice.
Try it yourself
Store a week of temperatures in an array and find the warmest day.
warmest: Thu (24.8°C)