Chapter 20: Go Arrays
Arrays in Go are very different from what most beginners expect. They are almost never the first choice when you want a “list of things” — that role belongs to slices.
Let’s go through everything about Go arrays like we’re sitting together with VS Code open, typing and running code live.
1. Core Facts About Arrays in Go
| Property | Explanation | Consequence / Gotcha |
|---|---|---|
| Fixed size | The size is part of the type — [5]int is different type from [6]int | Cannot grow or shrink after creation |
| Zero value | All elements get their zero value (0, “”, false, nil, etc.) | var a [10]int → all zeros |
| Value type | Arrays are copied when assigned or passed to functions (not reference like slices) | Big arrays = expensive copy |
| Contiguous memory | Elements are stored in continuous memory blocks | Very fast access (O(1)) |
| Length | len(a) is compile-time constant (fixed) | No dynamic resizing |
| Most common usage | Rare in everyday code — used mostly when size is known & fixed forever | Statistics, fixed-size buffers, crypto keys, coordinates |
Golden rule most people learn after 1–2 weeks:
In real Go code (2024–2026), you will use arrays directly < 5% of the time. 95%+ of the time when you want “a list”, you use slices ([]int, []string, etc.).
2. Declaration Styles (4 Main Ways)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package main import "fmt" func main() { // Style 1: full type + size + zero values var scores [5]int // [0, 0, 0, 0, 0] // Style 2: short declaration + size + values days := [7]string{ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", } // Style 3: size inferred from number of elements (very common) colors := [...]string{"red", "green", "blue"} // size = 3 // Style 4: sparse / indexed initialization numbers := [10]int{0: 100, 5: 500, 9: 999} // → [100, 0, 0, 0, 0, 500, 0, 0, 0, 999] fmt.Printf("scores: %v (len=%d)\n", scores, len(scores)) fmt.Printf("days: %q (len=%d)\n", days, len(days)) fmt.Printf("colors: %q (len=%d)\n", colors, len(colors)) fmt.Printf("numbers:%v\n", numbers) } |
3. Very Important: Arrays Are Value Types (Copy on Assignment)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
a := [3]int{1, 2, 3} b := a // ← full copy is made b[0] = 99 fmt.Println(a) // [1 2 3] ← a unchanged! fmt.Println(b) // [99 2 3] |
Slices behave differently (reference type) — that’s why slices are used much more often.
4. Arrays as Function Parameters (Copy vs Pointer)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
func printArray(arr [5]int) { arr[0] = 999 // only changes local copy fmt.Println("Inside func:", arr) } func main() { data := [5]int{10, 20, 30, 40, 50} printArray(data) fmt.Println("After func:", data) // still [10 20 30 40 50] } |
To modify the original array → pass pointer:
|
0 1 2 3 4 5 6 7 8 9 10 11 |
func modifyArray(arr *[5]int) { arr[0] = 999 } modifyArray(&data) fmt.Println("After pointer modify:", data) // [999 20 30 40 50] |
But again: most people just use slices instead — no need to pass pointers or worry about size.
5. Real-World (Rare) Use Cases for Arrays in 2026
| Use case | Why array instead of slice? | Example type |
|---|---|---|
| Fixed-size cryptographic key / hash | Size must be exactly 32 or 64 bytes | [32]byte |
| RGB / RGBA color | Always exactly 3 or 4 components | [4]uint8 |
| 3D point / vector | Always x,y,z (or x,y,z,w) | [3]float64 |
| Small fixed lookup table | Performance + compile-time size | [256]byte (ASCII map) |
| Matrix / small fixed grid | Known dimensions at compile time | [3][3]int |
| Interop with C code (cgo) | C arrays have fixed size | [64]byte |
6. Quick Comparison: Array vs Slice (Very Important Table)
| Feature | Array [n]T | Slice []T | Winner in practice |
|---|---|---|---|
| Size in type | Yes — part of type | No | Slice |
| Can grow / shrink | No | Yes (append) | Slice |
| Zero value | Zeroed elements | nil | Slice (more useful) |
| Copy on assignment | Full copy | Copy of descriptor (cheap) | Slice |
| Pass to function | Copy (expensive for large n) | Cheap (pointer-like) | Slice |
| len() at compile time? | Yes | No (runtime) | Array (rare benefit) |
| Most idiomatic usage 2026 | <5% | >95% | Slice |
7. Your Quick Practice Exercise
Create arrays.go and try these:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package main import "fmt" func main() { // 1. Fixed week days var weekdays [7]string weekdays[0] = "Sunday" weekdays[1] = "Monday" // ... fill the rest fmt.Println("Weekdays:", weekdays) // 2. RGB color as array red := [3]uint8{255, 0, 0} fmt.Printf("Red color: %v\n", red) // 3. Try to show copy behavior a := [4]int{10, 20, 30, 40} b := a b[1] = 99 fmt.Println("a after copy change:", a) // unchanged fmt.Println("b after change: ", b) } |
Now change it to slice ([]int) and see the difference.
Questions now?
- Multidimensional arrays ([3][4]int)?
- Why len(array) is compile-time constant?
- How to convert array ↔ slice?
- Or ready to move to slices next (the real star)?
Keep typing and running these — once you really feel the difference between array & slice, a huge part of Go will suddenly make sense. You’re doing great! 💪🇮🇳 Let’s keep going! 🚀
