Arrays in Go (Golang)

An array in Go is a fixed-size, typed collection of elements. Unlike slices, arrays cannot be resized after declaration.
For instance, var numbers [5]int
declares an array of 5 integers.
Key characteristics:
Fixed length (part of its type)
Stored contiguously in memory
Zero-initialized by default
Can be passed by value (copy)
Example 1: Declaring and Accessing Array Elements
Let’s start simple.
package main
import "fmt"
func main() {
var scores [3]int
scores[0] = 85
scores[1] = 90
scores[2] = 78
fmt.Println("Student Scores:", scores)
}
🔧 Explanation:
Declared a fixed-size array of 3 integers.
Set values via index:
scores[0]
,scores[1]
, etc.Prints:
Student Scores: [85 90 78]
Arrays in Go are zero-indexed, so indexing starts at 0.
Example 2: Iterating Over an Array
You’ll often want to loop through an array — here’s how to do it cleanly with range
.
package main
import "fmt"
func main() {
fruits := [4]string{"apple", "banana", "mango", "peach"}
for i, fruit := range fruits {
fmt.Printf("Index %d: %s\n", i, fruit)
}
}
🔧 Explanation:
range
returns both index and value during iteration.Output:
Note: Arrays can also be iterated using a traditional
for
loop when needed.
Example 3: Passing Arrays to Functions
This is where Go arrays behave differently than slices.
package main
import "fmt"
func doubleValues(arr [3]int) {
for i := range arr {
arr[i] *= 2
}
fmt.Println("Inside function:", arr)
}
func main() {
values := [3]int{1, 2, 3}
doubleValues(values)
fmt.Println("Outside function:", values)
}
🔧 Explanation:
Arrays are passed by value, so a copy is made.
Modifications inside the function do not affect the original array.
If you pass an array of length other than 3, you’ll get this error.
Output:
Inside function: [2 4 6] Outside function: [1 2 3]
Want changes to persist? Use a pointer (
*[3]int
) or switch to a slice ([]int
).
Example 4: Using a Pointer to Modify the Array
package main
import "fmt"
func modifyArray(arr *[3]int) {
arr[0] = 99
}
func main() {
original := [3]int{1, 2, 3}
modifyArray(&original)
fmt.Println("After function:", original)
}
Output:
After function: [99 2 3]
Why? Passing a pointer (*[3]int
) means you're modifying the actual array, not a copy. We’ll see in next blog how we can utilise slice for the same purpose.
Example 5: Array Initialization & Defaults
package main
import "fmt"
func main() {
var a [5]int // array of 5 integers, default initialized to 0
b := [3]string{"Go", "Rust", "C++"} // explicit initializer
c := [...]float64{3.14, 2.71, 1.61} // size inferred
fmt.Println("a:", a)
fmt.Println("b:", b)
fmt.Println("c:", c)
}
Arrays are zero-initialized by default.
The
[...]type{}
syntax allows the compiler to infer array length.Array length is part of its type:
[3]string
≠[4]string
.
Example 6: Arrays are Value Types(Copy-on-assign)
package main
import "fmt"
func main() {
a := [3]int{10, 20, 30}
b := a // creates a **copy**
b[0] = 99
fmt.Println("Original a:", a)
fmt.Println("Modified b:", b)
}
outputs:
Original a: [10 20 30]
Modified b: [99 20 30]
Assigning an array to a new variable creates a copy, not a shared reference. This is unlike slices or arrays in many other languages (like Java or Python).
Example 7: Arrays are comparable
package main
import "fmt"
func main() {
a := [3]int{1, 2, 3}
b := [3]int{1, 2, 3}
c := [3]int{3, 2, 1}
fmt.Println("a == b:", a == b)
fmt.Println("a == c:", a == c)
}
outputs:
a == b: true
a == c: false
Go lets you compare arrays directly if their element types are comparable. Slices cannot be compared this way ([]int == []int
is a compile-time error).
Example 8: Iterate over Arrays using for
package main
import "fmt"
func main() {
arr := [4]int{10, 20, 30, 40}
for i := 0; i < len(arr); i++ {
fmt.Printf("Element at index %d is %d\n", i, arr[i])
}
}
Gives you full control over the loop.
Useful when:
You want to loop in reverse
You want to skip or jump indices
You want more control over performance
Pro Tips on Using Arrays in Go
When to use arrays:
Fixed-size data
Predictable memory usage
Performance-critical paths
Arrays are useful under the hood — slices in Go are built on top of arrays.
For dynamic data, slices are almost always the better choice.
Wrapping Up
While arrays in Go are less commonly used directly, understanding their structure and behavior is critical for writing performant and predictable Go code. They form the bedrock of slices, and knowing how they work helps you write better memory-safe programs.
In the next post, we’ll take this forward by deep-diving into slices — Go’s dynamic powerhouse built on arrays.
Subscribe to my newsletter
Read articles from Bhuwan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
