Menu

Golang Array: Fixed Length, Value Semantics, vs Slices

A Go array has a fixed length that is part of its type, and it is copied on assignment. Learn how to declare, iterate, compare and pass arrays, and why most Go code uses slices instead.

This page includes runnable editors - edit, run, and see output instantly.

Declaring an array

An array type is written [N]T: a length, then an element type. The length is fixed at compile time and is part of the type.

Output:

[90 0 0 0 75] 5
Tue
[5]int [2 3 5 7 11]
["" "b" "" "d" ""]

An array is always fully initialized. Elements you do not set hold the zero value of the element type: 0, "", false, nil.

Indexing and bounds

Indexes run from 0 to len(a)-1. A constant index out of range is a compile error. A variable index out of range panics at run time.

var a [3]int
a[5] = 1 // compile error: invalid argument: index 5 out of bounds [0:3]

i := 5
a[i] = 1 // panic: runtime error: index out of range [5] with length 3

Iterating

for i, v := range a visits each element in order. v is a copy of the element, so assigning to v does not change the array. Write through the index instead.

There is one more subtlety specific to arrays: range over an array value evaluates a copy of the array up front. If the body modifies later elements, v still shows the old values. Ranging over &a or a[:] avoids the copy.

Arrays are values

This is the main difference from arrays in C, Java or JavaScript. Assigning an array copies every element. Passing an array to a function copies it too.

Output:

[1 2 3] [99 2 3]
[1 2 3]
[0 2 3]

Copying is cheap for small arrays and expensive for big ones: passing a [1_000_000]int by value copies eight megabytes. Pass a pointer (*[N]T) or a slice (a[:]) when the array is large or the function needs to change it. Indexing through an array pointer needs no explicit *: a[0] works on a *[3]int.

Comparing arrays and using them as map keys

Arrays of comparable elements support == and !=. Two arrays are equal when every element is equal. That also makes them valid map keys, which slices are not.

Arrays of different lengths are different types and cannot be compared at all: [3]int{} == [4]int{} does not compile (mismatched types [3]int and [4]int).

Multidimensional arrays

An array of arrays gives you a fixed grid. The whole grid is one contiguous block of memory.

row[:] turns the [3]rune row into a []rune slice, which string() accepts.

Arrays vs slices

Array [N]TSlice []T
Lengthfixed, part of the typechanges with append
Assignment and passingcopies all elementscopies a small header, shares elements
Zero valueN zero elementsnil, length 0
==yes, element by elementonly against nil
Map keyyesno
Typical usefixed-size data: hashes, coordinates, buffersalmost everything else

In practice you will mostly meet arrays in a few places: sha256.Sum256 returns a [32]byte, lookup tables whose size never changes, and as the backing store of a slice. Slicing an array with a[:] or a[1:3] creates a slice that shares its memory; the slices page covers what that sharing means.

Converting between arrays and slices

Converting a slice to an array (Go 1.20) or an array pointer (Go 1.17) panics if the slice is shorter than the array length: panic: runtime error: cannot convert slice with length 2 to array or pointer to array with length 3.

Common mistakes

  • Expecting a function to modify an array argument. It gets a copy. Pass *[N]T or a slice.
  • Using an array where a slice is wanted. []int{1, 2} is a slice, [2]int{1, 2} is an array. A function taking []int will not accept a [2]int; pass a[:].
  • Large arrays in a range loop. for _, v := range bigArray copies the whole array first. Range over &bigArray or a slice.

Frequently Asked Questions

How do you declare an array in Go?

Write the length in brackets before the element type: var a [5]int makes five zeros. With values: a := [3]string{"x", "y", "z"}. Use [...] to let the compiler count: a := [...]int{1, 2, 3} has type [3]int.

What is the difference between an array and a slice in Go?

An array has a fixed length that is part of its type ([3]int and [4]int are different types) and is copied when assigned or passed. A slice ([]int) is a view onto an underlying array with a length that can change through append, and copying a slice copies only the view, not the elements. Most Go code uses slices.

How do I get the length of an array in Go?

Use the built-in len(a). For an array it is a compile-time constant, so you can use it in constant expressions. cap(a) returns the same number.

Can you compare arrays in Go?

Yes, with == and !=, if the element type is comparable. Two arrays are equal when all their elements are equal. Arrays can also be map keys. Slices cannot be compared with == (except to nil); use slices.Equal for them.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED