Arrays
Reviewed & published by Brayan K
Arrays are the fixed-size foundation that slices (your next lesson) are built on. You'll learn to declare them, index them, and — crucially — understand that Go arrays are values: copying or passing one copies every element. That single fact explains a lot of Go behaviour.
Part of the free Go course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
- Declare arrays with a fixed length in the type
- Read and write elements by 0-based index
- Use array literals and the [...] auto-count form
- Iterate arrays with range and len
- Understand arrays are VALUES (copied on assign/pass)
- Compare arrays of the same type with ==
1️⃣ Declaring & Indexing
An array's length is part of its type: [5]int and [3]int are different types that can't be mixed. Declared without values, every element starts at the element type's zero value. You index with square brackets, starting at 0, and len() tells you the length (which never changes).
package main
import "fmt"
func main() {
// An array has a FIXED length that is part of its type.
// [5]int and [3]int are DIFFERENT types.
var scores [5]int // five ints, all zero by default
fmt.Println(scores) // [0 0 0 0 0]
// Set and read elements by index (0-based).
scores[0] = 90
scores[4] = 75
fmt.Println(scores) // [90 0 0 0 75]
fmt.Println("first:", scores[0]) // first: 90
// Array literal — give the values up front.
primes := [4]int{2, 3, 5, 7}
fmt.Println(primes) // [2 3 5 7]
// len() reports the length (always the same for an array).
fmt.Println("length:", len(primes)) // length: 4
}2️⃣ The [...] Form & Iterating
Typing the count by hand is error-prone, so Go lets you write [...] and it counts the literal for you. You can also set elements by index inside a literal (handy for sparse data), and you iterate exactly like any collection — with range.
package main
import "fmt"
func main() {
// [...] lets Go COUNT the length from the literal for you.
days := [...]string{"Mon", "Tue", "Wed", "Thu", "Fri"}
fmt.Println("days:", len(days)) // days: 5
// You can index specific positions in a literal too.
// Here index 9 is set; the gaps fill with the zero value.
grades := [10]int{0: 100, 9: 55}
fmt.Println(grades) // [100 0 0 0 0 0 0 0 0 55]
// Sum the array with range.
nums := [...]int{4, 8, 15, 16, 23, 42}
sum := 0
for _, n := range nums {
sum += n
}
fmt.Println("sum:", sum) // sum: 108
}3️⃣ Arrays Are Values
This is the single most important thing about Go arrays. Assigning an array to another variable, or passing it to a function, copies every element. The original is untouched by changes to the copy. (Slices, next lesson, behave differently — they share underlying storage.) Because they're plain values, two arrays of the same type can be compared with ==.
package main
import "fmt"
func main() {
// KEY IDEA: arrays are VALUES. Assigning or passing an array
// COPIES the whole thing — changes to the copy don't affect
// the original. (This is different from slices, next lesson!)
a := [3]int{1, 2, 3}
b := a // b is a full, independent copy
b[0] = 99
fmt.Println("a:", a) // a: [1 2 3] (unchanged)
fmt.Println("b:", b) // b: [99 2 3]
// Passing to a function copies too.
double(a)
fmt.Println("after double:", a) // after double: [1 2 3]
// Arrays of the same type are comparable with ==.
fmt.Println(a == [3]int{1, 2, 3}) // true
}
func double(arr [3]int) {
for i := range arr {
arr[i] *= 2 // mutates the LOCAL copy only
}
}Your turn — declare a three-string array and fill the podium.
package main
import "fmt"
func main() {
// 🎯 YOUR TURN — replace each ___ then run it.
// 1) Declare an array of 3 strings called "podium"
var podium ___ // 👉 [3]string
// 2) Fill the places
podium[0] = "Gold"
podium[1] = "Silver"
podium[___] = "Bronze" // 👉 2 (the third, 0-based)
fmt.Println(podium)
// ✅ Expected output: [Gold Silver Bronze]
}Now average a set of temperature readings.
package main
import "fmt"
func main() {
// 🎯 YOUR TURN — finish the loop then run it.
temps := [...]int{20, 22, 19, 24}
total := 0
for _, t := range ___ { // 👉 temps
total += t
}
avg := total / len(temps)
fmt.Println("average:", avg)
// ✅ Expected output: average: 21
}🧩 Reorder Challenge
These lines declare an array and set three slots, but they're scrambled. Put them in order so the program prints [10 50 99] (assume a func main wraps them).
a[1] = 50
fmt.Println(a)
var a [3]int
a[0] = 10
a[2] = 99- var a [3]int
- fmt.Println(a)
Why: the array must exist (var a [3]int) before any index can be assigned. The three assignments fill positions 0, 1 and 2 — they can be in any order among themselves, but all must precede the Println. The result is [10 50 99].
Pro Tips
- 💡 You'll use slices far more than arrays. Arrays shine when the size is truly fixed (an RGB pixel [3]byte, a chessboard [8][8]).
- 💡 Prefer [...] over a hard-coded count in literals so the length always matches the data.
- 💡 Pass big arrays as a slice or pointer if you want to avoid copying the whole thing on every call.
- 💡 Arrays are comparable, so you can use a small fixed array as a map key — slices cannot do that.
Common Errors (and the fix)
- "index out of range [5] with length 5" — valid indexes are 0..len-1. The last element of a length-5 array is index 4, not 5.
- "cannot use x ([3]int) as [4]int value" — length is part of the type. A [3]int and a [4]int are incompatible; they can't be assigned to each other.
- "changing the array in a function doesn't stick" — that's expected: arrays are copied when passed. Use a slice or a pointer to *[N]T to mutate the original.
- "invalid operation: a == b (mismatched types)" — only arrays of the same type and length are comparable with ==.
📋 Quick Reference
| Task | Syntax |
|---|---|
| Declare (zeroed) | var a [5]int |
| Literal | a := [3]int{1, 2, 3} |
| Auto-count | a := [...]int{1, 2, 3} |
| Indexed literal | [5]int{0: 9, 4: 1} |
| Length | len(a) |
| Compare | a == b |
🧠 Quick Recall
Predict the output before you reveal the answer.
var a [3]int; fmt.Println(a)
[0 0 0] — a fresh array fills with the element type's zero value, which is 0 for int.
a := [2]int{1, 2}; b := a; b[0] = 9; fmt.Println(a[0])
1 — b := a copies the whole array, so changing b[0] leaves a untouched.
3 — [...] tells Go to count the three literal elements, so the length is 3.
Frequently Asked Questions
Q: Should I use arrays or slices?
Slices, almost always — they're flexible and resizable. Use a true array only when the length is genuinely fixed and known at compile time, or when you need value semantics and comparability.
Q: Why didn't my function change the array?
Arrays are copied when passed, so the function edited a copy. Pass a slice of the array (arr[:]) or a pointer (*[N]T) to mutate the original.
Q: Can I grow an array later?
No — an array's length is fixed forever. If you need to add elements, that's exactly what a slice is for (next lesson).
Mini-Challenge: Find the Maximum
Loop through the readings and track the largest value you've seen. Start max at the first element. Write it yourself and match the example output.
package main
import "fmt"
func main() {
// 🎯 MINI-CHALLENGE: Find the maximum
// Given the fixed array below, find and print the largest value
// WITHOUT using any library — just a loop and a comparison.
// Start your "max" at the first element, then compare the rest.
//
// ✅ Example output: max = 91
readings := [...]int{37, 91, 12, 88, 45}
// your code here
}🎉 Lesson Complete!
- ✅ An array's length is part of its type: [5]int ≠ [3]int
- ✅ Index from 0; un-set elements hold the zero value; len() never changes
- ✅ [...] lets Go count the literal for you
- ✅ Arrays are values — assigning or passing copies every element
- ✅ Same-type arrays are comparable with == and usable as map keys
Practice quiz
What is printed by: var scores [5]int; fmt.Println(scores)?
- [ ]
- [5]int{}
- [0 0 0 0 0]
- a nil error
Answer: [0 0 0 0 0]. A declared array fills every element with the element type's zero value, which is 0 for int.
Given a := [3]int{1,2,3}; b := a; b[0] = 99 — what is a[0]?
- 1
- 99
- 0
- undefined
Answer: 1. Arrays are values: b := a copies every element, so changing b leaves a untouched. a[0] is still 1.
What does len([...]string{"a","b","c"}) return?
- 0
- 2
- It is a compile error
- 3
Answer: 3. The [...] form tells Go to count the literal's elements, so the length is 3.
Are [3]int and [5]int the same type?
- Yes, both are int arrays
- No — the length is part of the type
- Only if they hold equal values
- Only inside a function
Answer: No — the length is part of the type. An array's length is part of its type, so [3]int and [5]int are different, incompatible types.
What is the valid index range for a length-5 array?
- 0 to 4
- 1 to 5
- 0 to 5
- 1 to 4
Answer: 0 to 4. Indexes are 0-based, so a length-5 array runs from index 0 to 4. Index 5 is out of range.
What does [10]int{0: 100, 9: 55} produce?
- [100 55]
- a compile error
- [100 0 0 0 0 0 0 0 0 55]
- [55 ... 100]
Answer: [100 0 0 0 0 0 0 0 0 55]. Indexed literals set positions 0 and 9; the gaps fill with the zero value 0.
If you pass an array to a function and it modifies elements, what does the caller see afterward?
- The changes — arrays are shared
- No changes — the array was copied
- A panic
- Only the first element changes
Answer: No changes — the array was copied. Passing an array copies it, so the function mutates a local copy and the original is unchanged.
Can two arrays of the same type be compared with ==?
- No, never
- Only pointers can
- Only with reflect
- Yes, if same type and length
Answer: Yes, if same type and length. Arrays of the same type and length are comparable with ==, comparing element by element.
After summing [...]int{4,8,15,16,23,42} with range, what is the total?
- 100
- 108
- 96
- 120
Answer: 108. 4+8+15+16+23+42 = 108.
Why can a fixed array be used as a map key but a slice cannot?
- Arrays are smaller
- Maps require pointers
- Arrays are comparable; slices are not
- Slices are immutable
Answer: Arrays are comparable; slices are not. Map keys must be comparable. Arrays are comparable with ==, but slices are not, so slices can't be keys.
Continue this course
- Previous: Functions and Methods
- Next: Slices — Go's powerful dynamic views over arrays — append, copy, slicing