An array is a numbered sequence of elements with a fixed length, set at compile time. Slices are far more common in practice, but arrays are actually what slices are built on.
Declare an Array
var a [5]int declares `a` as an array of 5 integers, all zero-valued.
var a [5]int
fmt.Println(a)[0 0 0 0 0]The [N]T{...} syntax declares and initializes an array in one line.
a := [5]int{1, 2, 3, 4, 5}
fmt.Println(a)[1 2 3 4 5][...]T lets the compiler count the elements from the literal.
a := [...]int{1, 2, 3, 4, 5}
fmt.Println(a, len(a))[1 2 3 4 5] 5Fewer values than the array's length leaves the rest zero-valued.
a := [5]int{1, 2}
fmt.Println(a)[1 2 0 0 0]key: value sets only that index. Every other index keeps its zero value.
a := [5]int{1: 10, 3: 20}
fmt.Println(a)[0 10 0 20 0]Notes on Arrays
The length lives inside the type, so [3]int and [4]int are two different types. A function that takes [3]int takes exactly that, and passing it a [4]int fails at compile time.
That is the reason most Go code reaches for a slice instead: one function then handles any length. Arrays pay for the restriction with a size the compiler knows, so len is a constant you can use wherever Go needs one, including the size of another array.
func sum(a [3]int) int {
total := 0
for _, v := range a {
total += v
}
return total
}
three := [3]int{1, 2, 3}
four := [4]int{1, 2, 3, 4}
fmt.Println(sum(three)) // 6
fmt.Printf("%T %T\n", three, four) // [3]int [4]int
// sum(four) does not compile:
// cannot use four (variable of type [4]int) as [3]int value
const n = len(four)
var scaled [n]int
fmt.Println(scaled) // [0 0 0 0]buf[:] hands you a slice pointing at the array's own storage, which is how a fixed buffer meets an API that wants []byte. Read fills buf itself, and the trailing zero is the byte it never reached.
Reslicing keeps that shared storage, so writing 'G' through s changes the array underneath it. This is the one place an array stops behaving like a value you copied.
var buf [8]byte
n, _ := strings.NewReader("go 1.26").Read(buf[:])
fmt.Println(n) // 7
fmt.Println(buf) // [103 111 32 49 46 50 54 0]
fmt.Printf("%q\n", buf[:n]) // "go 1.26"
s := buf[:3]
s[0] = 'G'
fmt.Printf("%q %q\n", s, buf[:n]) // "Go " "Go 1.26"Examples
Arrays are values. Assigning one, or passing it to a function, copies every element — unlike a slice, which shares its backing array.
a := [3]int{1, 2, 3}
b := a
b[0] = 99
fmt.Println(a, b)[1 2 3] [99 2 3]Two arrays are comparable with == when their element type is comparable and their lengths match. Slices have no such operator.
a := [3]int{1, 2, 3}
b := [3]int{1, 2, 3}
c := [3]int{1, 2, 4}
fmt.Println(a == b)
fmt.Println(a == c)true
falseAn array of arrays. [2][3]int is 2 rows of 3 ints each, indexed row then column.
var grid [2][3]int
grid[0][1] = 5
grid[1][2] = 9
fmt.Println(grid)[[0 5 0] [0 0 9]]range yields the index and a copy of the value at that index, in order.
a := [4]string{"a", "b", "c", "d"}
for i, v := range a {
fmt.Println(i, v)
}0 a
1 b
2 c
3 d