Golang - Data Structures - Arrays vs Slices

Publish date: 2025-09-05
Tags: <a href="https://programmercave.com/tags/Go/">Go</a>

Introduction

Arrays and Slices are both used for storing sequences of data, but they have fundamental differences in how they work.


The Core Difference: Fixed vs. Dynamic

Analogy: An array is like a shipping carton with a fixed number of slots. If you order a carton for 6 items, you get exactly 6 slots. You can’t add a 7th. A slice is like a movable, resizable window that you can place over a set of items in a warehouse (the underlying array).


Feature Comparison: Array vs. Slice

Feature Array Slice
Size Fixed. The length is part of its type. Dynamic. Can grow and shrink.
Type Declaration [5]int (length is specified) []int (length is omitted)
Memory Is a value type. Contains the data directly. Is a reference type. Contains a pointer to an underlying array.
Assignment Copies the entire array. Copies the slice header. Both slices point to the same data.
Function Passing Passed by value (the whole array is copied). Passed by value (the slice header is copied, but not the data).
Use Case Rarely used directly. Good for fixed data sets. The idiomatic choice for almost all collections in Go.

1. Arrays: The Rigid Foundation

An array’s type is defined by both its element type and its size. This means [3]int and [4]int are completely different, incompatible types.

Code Example: Arrays are Value Types

When you assign or pass an array, you are making a full copy of its data.

package main

import "fmt"

func main() {
	// arr1 is an array of 3 integers
	arr1 := [3]int{10, 20, 30}

	// arr2 is a COPY of arr1
	arr2 := arr1

	// Modifying arr2 does NOT affect arr1
	arr2[0] = 999

	fmt.Println("arr1:", arr1) // Output: arr1: [10 20 30]
	fmt.Println("arr2:", arr2) // Output: arr2: [999 20 30]
}

This copy-on-assignment behavior makes arrays inefficient for passing around in your application.


2. Slices: The Flexible View

A slice is a lightweight data structure that “describes” a contiguous section of an underlying array. It doesn’t store any data itself.

Code Example: Slices are Reference Types

When you assign or pass a slice, you copy the slice header, but both the original and the copy point to the same underlying array.

package main

import "fmt"

func main() {
	// slice1 is a slice of integers
	slice1 := []int{10, 20, 30}

	// slice2 refers to the SAME underlying data as slice1
	slice2 := slice1

	// Modifying slice2 WILL affect slice1
	slice2[0] = 999

	fmt.Println("slice1:", slice1) // Output: slice1: [999 20 30]
	fmt.Println("slice2:", slice2) // Output: slice2: [999 20 30]
}

This behavior makes slices very efficient to work with. Modifying a slice inside a function will be visible to the caller, which is usually the desired behavior.

Slices In-Depth

Mutability in Arrays vs. Slices


How to Choose?

Interview Question: “What’s the difference between an array and a slice?” Answer: “An array has a fixed size that’s part of its type, and it’s a value type, meaning it’s copied on assignment. A slice is a dynamic, reference type that provides a flexible view over an underlying array. Slices are far more common and idiomatic in Go.”

Tags: <a href="https://programmercave.com/tags/Go/">Go</a>